Setting up the data so that the difference between the SNAP data and the airport specific data.

Step 1: Extract the RCP Site data from the SNAP 5 model averages.

Step 2: Import both data sets

Step 3: Set up the Z-score calculation based on notes from meeting with Alan Hamlet

Step 4: Calculate the average and standard deviation of the daily differences

Step 5 (not in this file): rerun models with the new forecast temperatures – List these files here after the fact to make sure this is up to date

Load in the packages needed

library(dplyr)

Setting up the workspace

library(dplyr)
library(ggplot2)

setwd("~/Library/CloudStorage/Dropbox/SWEL/CopperRiverDelta/PondTemps/DataAnalysis/PondTempsAnalysis")

Extracting the RCP data from the aat file

Read in the data

load("~/Dropbox/SWEL/CopperRiverDelta/PondTemps/DataAnalysis/PondTempsAnalysis/forecasted_temperature.RData")

str(aat)
'data.frame':   32040 obs. of  7 variables:
 $ temperature: num  -7.1 -6.3 0 -8.3 -4.9 -3.4 -6.8 -12.5 -2.7 -6 ...
 $ rcp        : chr  "45" "45" "45" "45" ...
 $ model      : chr  "GFDL-CM3" "GFDL-CM3" "GFDL-CM3" "GFDL-CM3" ...
 $ month      : chr  "01" "01" "01" "01" ...
 $ year       : chr  "2012" "2013" "2014" "2015" ...
 $ site       : chr  "yak" "yak" "yak" "yak" ...
 $ date       : 'yearmon' num  Jan 2012 Jan 2013 Jan 2014 Jan 2015 ...

This comes in as a datafile with columns temperature, rcp, model, month, year, site, and date

Extract the data

# selecting CRD
CRD <- aat %>%
  dplyr::filter(site == "cord")

# filter for each rcp
CR_4.5 <- CRD %>%
  dplyr::filter(rcp == "45")

CR_6.0 <- CRD %>%
  dplyr::filter(rcp == "60")

CR_8.5 <- CRD %>%
  dplyr::filter(rcp == "85")

# selecting YF
YF <- aat %>%
  dplyr::filter(site == "yak")

# filter for each rcp
YF_4.5 <- YF %>%
  dplyr::filter(rcp == "45")

YF_6.0 <- YF %>%
  dplyr::filter(rcp == "60")

YF_8.5 <- YF%>%
  dplyr::filter(rcp == "85")
ggplot()+
   geom_smooth(data = CR_8.5, aes(x = date, y = temperature, color = "red")) +
   geom_smooth(data = CR_4.5, aes(x = date, y = temperature, color = "blue"))
Warning: The `trans` argument of `continuous_scale()` is deprecated as of ggplot2 3.5.0.
ℹ Please use the `transform` argument instead.
This warning is displayed once every 8 hours.
Call `lifecycle::last_lifecycle_warnings()` to see where this warning was generated.
`geom_smooth()` using method = 'gam' and formula = 'y ~ s(x, bs = "cs")'
`geom_smooth()` using method = 'gam' and formula = 'y ~ s(x, bs = "cs")'

NA
NA
NA

Starting with the RCP 4.5 data

Filtering to 4.5

CR_4.5

library(dplyr)
library(zoo)

# Convert the 'yearmon' numeric date to a proper Date object (first day of each month)
CR_4.5$date <- as.Date(as.yearmon(CR_4.5$date), frac = 0)

# Group by date (year and month combination) and calculate average temperature
avg_CR_4.5 <- CR_4.5 %>%
  group_by(date) %>%
  summarise(avg_temperature = mean(temperature, na.rm = TRUE),
            std_temperature = sd(temperature, na.rm = TRUE),
            precision = 1 / (sd(temperature, na.rm = TRUE)^2))

# View the resulting dataframe
print(avg_CR_4.5)

CR_4.5 <- avg_CR_4.5
CR_4.5
YF_4.5
# Convert the 'yearmon' numeric date to a proper Date object (first day of each month)
YF_4.5$date <- as.Date(as.yearmon(YF_4.5$date), frac = 0)

# Group by date (year and month combination) and calculate average temperature
avg_YF_4.5 <- YF_4.5 %>%
  group_by(date) %>%
  summarise(avg_temperature = mean(temperature, na.rm = TRUE),
            std_temperature = sd(temperature, na.rm = TRUE),
            precision = 1 / (sd(temperature, na.rm = TRUE)^2))

# View the resulting dataframe
print(avg_YF_4.5)

YF_4.5 <- avg_YF_4.5
YF_4.5

Plot the forecasted data

CR_4.5

# Full time frame (2006-2100)
CR_SNAP <- ggplot(data = CR_4.5, mapping = aes(x = date)) +
  geom_line(aes(y = avg_temperature), size = 0.8) +  # Line plot for avg_temperature
  geom_ribbon(aes(ymin = avg_temperature - std_temperature, 
                  ymax = avg_temperature + std_temperature),  # Ribbon for uncertainty
              alpha = 0.5, fill = "blue") +
  xlab("Year") +
  ylab("Mean Forecast Temperature") +
  ggtitle("Copper River SNAP Forecast - RCP 4.5") +
  theme_classic() +
  theme(plot.title = element_text(hjust = 0.5))
CR_SNAP


ggsave("CR_Geo_Forecast4.5_2020.jpeg", plot = CR_SNAP, width = 8, height = 6)

YF_4.5

# Full time frame (2006-2100)
YF_SNAP <- ggplot(data = YF_4.5, mapping = aes(x = date)) +
  geom_line(aes(y = avg_temperature), size = 0.8) +  # Line plot for avg_temperature
  geom_ribbon(aes(ymin = avg_temperature - std_temperature,
                  ymax = avg_temperature + std_temperature),  # Ribbon for uncertainty
              alpha = 0.5, fill = "blue") +
  xlab("Year") +
  ylab("Mean Forecast Temperature") +
  ggtitle("Yakutat Foreland SNAP Forecast - RCP 4.5") +
  theme_classic() +
  theme(plot.title = element_text(hjust = 0.5))
YF_SNAP


ggsave("YF_Geo_Forecast4.5_2020.jpeg", plot = YF_SNAP, width = 8, height = 6)

Continuing with the RCP 6.0 data

Filtering to 6.0

CR_6.0

# Convert the 'yearmon' numeric date to a proper Date object (first day of each month)
CR_6.0$date <- as.Date(as.yearmon(CR_6.0$date), frac = 0)

# Group by date (year and month combination) and calculate average temperature
avg_CR_6.0 <- CR_6.0 %>%
  group_by(date) %>%
  summarise(avg_temperature = mean(temperature, na.rm = TRUE),
            std_temperature = sd(temperature, na.rm = TRUE),
            precision = 1 / (sd(temperature, na.rm = TRUE)^2))

# View the resulting dataframe
print(avg_CR_6.0)

CR_6.0 <- avg_CR_6.0
CR_6.0
YF_6.0

# Convert the 'yearmon' numeric date to a proper Date object (first day of each month)
YF_6.0$date <- as.Date(as.yearmon(YF_6.0$date), frac = 0)

# Group by date (year and month combination) and calculate average temperature
avg_YF_6.0 <- YF_6.0 %>%
  group_by(date) %>%
  summarise(avg_temperature = mean(temperature, na.rm = TRUE),
            std_temperature = sd(temperature, na.rm = TRUE),
            precision = 1 / (sd(temperature, na.rm = TRUE)^2))

# View the resulting dataframe
print(avg_YF_6.0)

YF_6.0 <- avg_YF_6.0
YF_6.0

Plot the forecasted data

CR_6.0

# Full time frame (2006-2100)
CR_SNAP <- ggplot(data = CR_6.0, mapping = aes(x = date)) +
  geom_line(aes(y = avg_temperature), size = 0.8) +  # Line plot for avg_temperature
  geom_ribbon(aes(ymin = avg_temperature - std_temperature, 
                  ymax = avg_temperature + std_temperature),  # Ribbon for uncertainty
              alpha = 0.5, fill = "blue") +
  xlab("Year") +
  ylab("Mean Forecast Temperature") +
  ggtitle("Copper River SNAP Forecast - RCP 6.0") +
  theme_classic() +
  theme(plot.title = element_text(hjust = 0.5))
CR_SNAP


ggsave("CR_Geo_Forecast6.0_2020.jpeg", plot = CR_SNAP, width = 8, height = 6)

YF_6.0

# Full time frame (2006-2100)
YF_SNAP <- ggplot(data = YF_6.0, mapping = aes(x = date)) +
  geom_line(aes(y = avg_temperature), size = 0.8) +  # Line plot for avg_temperature
  geom_ribbon(aes(ymin = avg_temperature - std_temperature,
                  ymax = avg_temperature + std_temperature),  # Ribbon for uncertainty
              alpha = 0.5, fill = "blue") +
  xlab("Year") +
  ylab("Mean Forecast Temperature") +
  ggtitle("Yakutat Foreland SNAP Forecast - RCP 6.0") +
  theme_classic() +
  theme(plot.title = element_text(hjust = 0.5))
YF_SNAP


ggsave("YF_Geo_Forecast6.0_2020.jpeg", plot = YF_SNAP, width = 8, height = 6)

Continuing with the RCP 8.5 data

Filtering to 8.5

CR_8.5

# Convert the 'yearmon' numeric date to a proper Date object (first day of each month)
CR_8.5$date <- as.Date(as.yearmon(CR_8.5$date), frac = 0)

# Group by date (year and month combination) and calculate average temperature
avg_CR_8.5 <- CR_8.5 %>%
  group_by(date) %>%
  summarise(avg_temperature = mean(temperature, na.rm = TRUE),
            std_temperature = sd(temperature, na.rm = TRUE),
            precision = 1 / (sd(temperature, na.rm = TRUE)^2))

# View the resulting dataframe
print(avg_CR_8.5)

CR_8.5 <- avg_CR_8.5
CR_8.5
YF_8.5

# Convert the 'yearmon' numeric date to a proper Date object (first day of each month)
YF_8.5$date <- as.Date(as.yearmon(YF_8.5$date), frac = 0)

# Group by date (year and month combination) and calculate average temperature
avg_YF_8.5 <- YF_8.5 %>%
  group_by(date) %>%
  summarise(avg_temperature = mean(temperature, na.rm = TRUE),
            std_temperature = sd(temperature, na.rm = TRUE),
            precision = 1 / (sd(temperature, na.rm = TRUE)^2))

# View the resulting dataframe
print(avg_YF_8.5)

YF_8.5 <- avg_YF_8.5
YF_8.5

Plot the forecasted data

CR_8.5

# Full time frame (2006-2100)
CR_SNAP <- ggplot(data = CR_8.5, mapping = aes(x = date)) +
  geom_line(aes(y = avg_temperature), size = 0.8) +  # Line plot for avg_temperature
  geom_ribbon(aes(ymin = avg_temperature - std_temperature, 
                  ymax = avg_temperature + std_temperature),  # Ribbon for uncertainty
              alpha = 0.5, fill = "blue") +
  xlab("Year") +
  ylab("Mean Forecast Temperature") +
  ggtitle("Copper River SNAP Forecast - RCP 8.5") +
  theme_classic() +
  theme(plot.title = element_text(hjust = 0.5))
CR_SNAP


ggsave("CR_Geo_Forecast8.5_2020.jpeg", plot = CR_SNAP, width = 8, height = 6)

YF_8.5

# Full time frame (2006-2100)
YF_SNAP <- ggplot(data = YF_8.5, mapping = aes(x = date)) +
  geom_line(aes(y = avg_temperature), size = 0.8) +  # Line plot for avg_temperature
  geom_ribbon(aes(ymin = avg_temperature - std_temperature,
                  ymax = avg_temperature + std_temperature),  # Ribbon for uncertainty
              alpha = 0.5, fill = "blue") +
  xlab("Year") +
  ylab("Mean Forecast Temperature") +
  ggtitle("Yakutat Foreland SNAP Forecast - RCP 8.5") +
  theme_classic() +
  theme(plot.title = element_text(hjust = 0.5))
YF_SNAP


ggsave("YF_Geo_Forecast8.5_2020.jpeg", plot = YF_SNAP, width = 8, height = 6)

Saving the data as datafiles for later use

write.csv(YF_4.5, file = "BiasCorrection/Geo_BiasCorrection/DataFiles/SNAP_YF45.csv", row.names = FALSE)
write.csv(YF_6.0, file = "BiasCorrection/Geo_BiasCorrection/DataFiles/SNAP_YF60.csv", row.names = FALSE)
write.csv(YF_8.5, file = "BiasCorrection/Geo_BiasCorrection/DataFiles/SNAP_YF85.csv", row.names = FALSE)

write.csv(CR_4.5, file = "BiasCorrection/Geo_BiasCorrection/DataFiles/SNAP_CR45.csv", row.names = FALSE)
write.csv(CR_6.0, file = "BiasCorrection/Geo_BiasCorrection/DataFiles/SNAP_CR60.csv", row.names = FALSE)
write.csv(CR_8.5, file = "BiasCorrection/Geo_BiasCorrection/DataFiles/SNAP_CR85.csv", row.names = FALSE)

If these above is already done, start here and just read in the files that were created ^

YF_45 <- read.csv(file = "BiasCorrection/Geo_BiasCorrection/DataFiles/SNAP_YF45.csv") 
YF_45$date <- as.Date(YF_45$date,format="%Y-%m-%d")
YF_85 <- read.csv(file = "BiasCorrection/Geo_BiasCorrection/DataFiles/SNAP_YF85.csv")
YF_85$date <- as.Date(YF_85$date,format="%Y-%m-%d")

CR_45 <- read.csv(file = "BiasCorrection/Geo_BiasCorrection/DataFiles/SNAP_CR45.csv")
CR_45$date <- as.Date(CR_45$date,format="%Y-%m-%d")
CR_85 <- read.csv(file = "BiasCorrection/Geo_BiasCorrection/DataFiles/SNAP_CR85.csv")
CR_85$date <- as.Date(CR_85$date,format="%Y-%m-%d")

Read in the data file for the airport temperature data Separate this by airport location

CRD_airport <- read.csv(file = "BiasCorrection/CR_PondAirTemp_mean.csv")
CRD_airport <- CRD_airport %>%
  select(-X)

YF_airport <- read.csv(file = "BiasCorrection/YF_PondAirTemp_mean.csv")
YF_airport <- YF_airport %>%
  select(-X)

Copper River Delta RCP 4.5

  1. Read in the data
# Read data files
CR_45 <- read.csv(file = "BiasCorrection/Geo_BiasCorrection/DataFiles/SNAP_CR45.csv") 
CR_45$date <- as.Date(CR_45$date,format="%Y-%m-%d")
CRD_airport <- read.csv(file = "BiasCorrection/CR_PondAirTemp_mean.csv")
CRD_airport$Date <- as.Date(CRD_airport$Date, format = "%Y-%m-%d")
CRD_airport <- CRD_airport %>% select(-X)  # Remove unnecessary column 'X'
  1. Check dates
# Ensure that there are no NAs in the 'date' column after conversion
sum(is.na(CR_45$date))  # Check if there are any missing values (should be 0)
[1] 0
  1. Trim dates
# Trim CR_45 to the date range of CRD_airport
start_date <- min(CRD_airport$Date)
end_date <- max(CRD_airport$Date)

# Subset CR_45 to match the date range of CRD_airport
CR_45_trimmed <- CR_45 %>%
  filter(date >= start_date & date <= end_date)
  1. Plot pre-correction data
library(ggplot2)

# Ensure 'Date' in CRD_airport is in Date format
CRD_airport$Date <- as.Date(CRD_airport$Date)

# Plot Observed vs Uncorrected Predicted Temperatures
Plot <- ggplot() +
  geom_line(data = CR_45_trimmed, aes(x = date, y = avg_temperature, color = "Predicted (Uncorrected)"), size = 1.2) +
  geom_line(data = CRD_airport, aes(x = Date, y = Air_MonthAvg, color = "Observed"), size = 1.2) +
  labs(
    title = "Observed vs Uncorrected Predicted Temperatures - CR 4.5",
    x = "Date",
    y = "Temperature (°C)",
    color = "Temperature Type"
  ) +
  scale_x_date(
    date_labels = "%b %Y",
    date_breaks = "1 month",
    expand = c(0, 0)
  ) +
  scale_color_manual(values = c("Predicted (Uncorrected)" = "red", "Observed" = "black")) +
  theme_minimal() +
  theme(
    axis.text.x = element_text(angle = 45, hjust = 1),
    axis.title = element_text(size = 12),
    axis.text = element_text(size = 10),
    plot.title = element_text(size = 14, face = "bold"),
    legend.title = element_text(size = 12),
    legend.text = element_text(size = 10)
  )
Plot

ggsave("BiasCorrection/Geo_BiasCorrection/Plots/Pre-CorrectionComparison_CR45.jpeg", plot = Plot, width = 8, height = 6)

  1. Monthly z-score bias correction
# Add "month" column for grouping
CR_45_trimmed$month <- format(CR_45_trimmed$date, "%m")
CRD_airport$month <- format(CRD_airport$Date, "%m")

# Calculate monthly means and standard deviations for observed and predicted temperatures
obs_monthly_stats <- CRD_airport %>%
  group_by(month) %>%
  summarise(
    mu_obs = mean(Air_MonthAvg, na.rm = TRUE),
    sigma_obs = sd(Air_MonthAvg, na.rm = TRUE)
  )

pred_monthly_stats <- CR_45_trimmed %>%
  group_by(month) %>%
  summarise(
    mu_pred = mean(avg_temperature, na.rm = TRUE),
    sigma_pred = sd(avg_temperature, na.rm = TRUE)
  )

# Merge statistics back into the dataset
CR_45_trimmed <- CR_45_trimmed %>%
  left_join(obs_monthly_stats, by = "month") %>%
  left_join(pred_monthly_stats, by = "month")

# Apply bias correction
CR_45_trimmed <- CR_45_trimmed %>%
  mutate(
    corrected_temp = (avg_temperature - mu_pred) / sigma_pred * sigma_obs + mu_obs
  )
  1. Plot corrected data
# Plotting Observed vs Corrected Predicted Temperatures
Plot <- ggplot() +
  geom_line(data = CR_45_trimmed, aes(x = date, y = corrected_temp, color = "Predicted (Corrected)"), size = 1.2, linetype = "dashed") +
  geom_line(data = CRD_airport, aes(x = Date, y = Air_MonthAvg, color = "Observed"), size = 1.2) +
  labs(
    title = "Observed vs Corrected Predicted Temperatures - CR RCP 4.5",
    x = "Date",
    y = "Temperature (°C)",
    color = "Temperature Type"
  ) +
  scale_x_date(
    date_labels = "%b %Y",
    date_breaks = "1 month",
    expand = c(0, 0)
  ) +
  scale_color_manual(values = c("Predicted (Corrected)" = "blue", "Observed" = "black")) +
  theme_minimal() +
  theme(
    axis.text.x = element_text(angle = 45, hjust = 1),
    axis.title = element_text(size = 12),
    axis.text = element_text(size = 10),
    plot.title = element_text(size = 14, face = "bold"),
    plot.subtitle = element_text(size = 12, face = "italic"),
    legend.title = element_text(size = 12),
    legend.text = element_text(size = 10)
  )
Plot

ggsave("BiasCorrection/Geo_BiasCorrection/Plots/Corrected_CR45.jpeg", plot = Plot, width = 8, height = 6)

  1. Correction applied to the whole dataset
# Add "month" column to the full dataset
CR_45$month <- format(CR_45$date, "%m")

# Merge monthly statistics into the full dataset
CR_45 <- CR_45 %>%
  left_join(obs_monthly_stats, by = "month") %>%
  left_join(pred_monthly_stats, by = "month")

# Apply the z-score bias correction
CR_45 <- CR_45 %>%
  mutate(
    corrected_temp = (avg_temperature - mu_pred) / sigma_pred * sigma_obs + mu_obs
  )
  1. Plot corrected and uncorrected temperatures together
# Plot the full dataset with adjusted x-axis limits
Plot <- ggplot() +
  geom_line(data = CR_45, aes(x = date, y = avg_temperature, color = "Predicted (Uncorrected)"), size = 1.2) +
  geom_line(data = CR_45, aes(x = date, y = corrected_temp, color = "Predicted (Corrected)"), size = 1.2, linetype = "dashed") +
  labs(
    title = "Original vs Corrected Predicted Temperatures - CR RCP 4.5",
    x = "Date",
    y = "Temperature (°C)",
    color = "Temperature Type"
  ) +
  scale_x_date(
    limits = as.Date(c("2012-01-01", "2020-12-01")), # Set x-axis limits
    date_labels = "%b %Y",
    date_breaks = "1 month",
    expand = c(0, 0)
  ) +
  scale_color_manual(values = c("Predicted (Uncorrected)" = "red", "Predicted (Corrected)" = "blue")) +
  theme_minimal() +
  theme(
    axis.text.x = element_text(angle = 45, hjust = 1),
    axis.title = element_text(size = 12),
    axis.text = element_text(size = 10),
    plot.title = element_text(size = 14, face = "bold"),
    legend.title = element_text(size = 12),
    legend.text = element_text(size = 10)
  )
Plot
Warning: Removed 960 rows containing missing values or values outside the scale range (`geom_line()`).
Warning: Removed 960 rows containing missing values or values outside the scale range (`geom_line()`).
ggsave("BiasCorrection/Geo_BiasCorrection/Plots/CorrectionComparison_CR45.jpeg", plot = Plot, width = 8, height = 6)
Warning: Removed 960 rows containing missing values or values outside the scale range (`geom_line()`).
Warning: Removed 960 rows containing missing values or values outside the scale range (`geom_line()`).

  1. Plot original versus corrected temperatures
# Plot the full dataset
Plot <- ggplot() +
  geom_line(data = CR_45, aes(x = date, y = avg_temperature, color = "Predicted (Uncorrected)"), size = 1.2) +
  geom_line(data = CR_45, aes(x = date, y = corrected_temp, color = "Predicted (Corrected)"), size = 1.2, linetype = "dashed") +
  geom_line(data = CRD_airport, aes(x = Date, y = Air_MonthAvg, color = "Observed"), size = 1.2) +
  labs(
    title = "Original vs Corrected Predicted Temperatures - CR RCP 4.5",
    x = "Date",
    y = "Temperature (°C)",
    color = "Temperature Type"
  ) +
  scale_x_date(
    date_labels = "%b %Y",
    date_breaks = "1 month",
    expand = c(0, 0)
  ) +
  scale_color_manual(values = c("Predicted (Uncorrected)" = "red", "Predicted (Corrected)" = "blue")) +
  theme_minimal() +
  theme(
    axis.text.x = element_text(angle = 45, hjust = 1),
    axis.title = element_text(size = 12),
    axis.text = element_text(size = 10),
    plot.title = element_text(size = 14, face = "bold"),
    legend.title = element_text(size = 12),
    legend.text = element_text(size = 10)
  )
Plot

ggsave("BiasCorrection/Geo_BiasCorrection/Plots/FullCorrection_CR45.jpeg", plot = Plot, width = 8, height = 6)

  1. Save the new file
# Save the corrected dataset to a CSV file
write.csv(CR_45, "BiasCorrection/Geo_BiasCorrection/DataFiles/SNAP_CR45_corrected_monthly.csv", row.names = FALSE)

Copper River Delta RCP 8.5

  1. Read in the data
# Read data files
CR_85 <- read.csv(file = "BiasCorrection/Geo_BiasCorrection/DataFiles/SNAP_CR85.csv") 
CR_85$date <- as.Date(CR_85$date,format="%Y-%m-%d")
CRD_airport <- read.csv(file = "BiasCorrection/CR_PondAirTemp_mean.csv")
CRD_airport <- CRD_airport %>% select(-X)  # Remove unnecessary column 'X'
  1. Check dates
# Ensure that there are no NAs in the 'date' column after conversion
sum(is.na(CR_85$date))  # Check if there are any missing values (should be 0)
[1] 0
  1. Trim dates
# Trim CR_85 to the date range of CRD_airport
start_date <- min(CRD_airport$Date)
end_date <- max(CRD_airport$Date)

# Subset CR_85 to match the date range of CRD_airport
CR_85_trimmed <- CR_85 %>%
  filter(date >= start_date & date <= end_date)
  1. Plot pre-correction data
library(ggplot2)

# Ensure 'Date' in CRD_airport is in Date format
CRD_airport$Date <- as.Date(CRD_airport$Date)

# Plot Observed vs Uncorrected Predicted Temperatures
Plot <- ggplot() +
  geom_line(data = CR_85_trimmed, aes(x = date, y = avg_temperature, color = "Predicted (Uncorrected)"), size = 1.2) +
  geom_line(data = CRD_airport, aes(x = Date, y = Air_MonthAvg, color = "Observed"), size = 1.2) +
  labs(
    title = "Observed vs Uncorrected Predicted Temperatures - CR 8.5",
    x = "Date",
    y = "Temperature (°C)",
    color = "Temperature Type"
  ) +
  scale_x_date(
    date_labels = "%b %Y",
    date_breaks = "1 month",
    expand = c(0, 0)
  ) +
  scale_color_manual(values = c("Predicted (Uncorrected)" = "red", "Observed" = "black")) +
  theme_minimal() +
  theme(
    axis.text.x = element_text(angle = 85, hjust = 1),
    axis.title = element_text(size = 12),
    axis.text = element_text(size = 10),
    plot.title = element_text(size = 14, face = "bold"),
    legend.title = element_text(size = 12),
    legend.text = element_text(size = 10)
  )
Plot

ggsave("BiasCorrection/Geo_BiasCorrection/Plots/Pre-CorrectionComparison_CR85.jpeg", plot = Plot, width = 8, height = 6)

  1. Monthly z-score bias correction
# Add "month" column for grouping
CR_85_trimmed$month <- format(CR_85_trimmed$date, "%m")
CRD_airport$month <- format(CRD_airport$Date, "%m")

# Calculate monthly means and standard deviations for observed and predicted temperatures
obs_monthly_stats <- CRD_airport %>%
  group_by(month) %>%
  summarise(
    mu_obs = mean(Air_MonthAvg, na.rm = TRUE),
    sigma_obs = sd(Air_MonthAvg, na.rm = TRUE)
  )

pred_monthly_stats <- CR_85_trimmed %>%
  group_by(month) %>%
  summarise(
    mu_pred = mean(avg_temperature, na.rm = TRUE),
    sigma_pred = sd(avg_temperature, na.rm = TRUE)
  )

# Merge statistics back into the dataset
CR_85_trimmed <- CR_85_trimmed %>%
  left_join(obs_monthly_stats, by = "month") %>%
  left_join(pred_monthly_stats, by = "month")

# Apply bias correction
CR_85_trimmed <- CR_85_trimmed %>%
  mutate(
    corrected_temp = (avg_temperature - mu_pred) / sigma_pred * sigma_obs + mu_obs
  )
  1. Plot corrected data
# Plotting Observed vs Corrected Predicted Temperatures
Plot <- ggplot() +
  geom_line(data = CR_85_trimmed, aes(x = date, y = corrected_temp, color = "Predicted (Corrected)"), size = 1.2, linetype = "dashed") +
  geom_line(data = CRD_airport, aes(x = Date, y = Air_MonthAvg, color = "Observed"), size = 1.2) +
  labs(
    title = "Observed vs Corrected Predicted Temperatures - CR RCP 8.5",
    x = "Date",
    y = "Temperature (°C)",
    color = "Temperature Type"
  ) +
  scale_x_date(
    date_labels = "%b %Y",
    date_breaks = "1 month",
    expand = c(0, 0)
  ) +
  scale_color_manual(values = c("Predicted (Corrected)" = "blue", "Observed" = "black")) +
  theme_minimal() +
  theme(
    axis.text.x = element_text(angle = 85, hjust = 1),
    axis.title = element_text(size = 12),
    axis.text = element_text(size = 10),
    plot.title = element_text(size = 14, face = "bold"),
    plot.subtitle = element_text(size = 12, face = "italic"),
    legend.title = element_text(size = 12),
    legend.text = element_text(size = 10)
  )
Plot

ggsave("BiasCorrection/Geo_BiasCorrection/Plots/Corrected_CR85.jpeg", plot = Plot, width = 8, height = 6)

  1. Correction applied to the whole dataset
# Add "month" column to the full dataset
CR_85$month <- format(CR_85$date, "%m")

# Merge monthly statistics into the full dataset
CR_85 <- CR_85 %>%
  left_join(obs_monthly_stats, by = "month") %>%
  left_join(pred_monthly_stats, by = "month")

# Apply the z-score bias correction
CR_85 <- CR_85 %>%
  mutate(
    corrected_temp = (avg_temperature - mu_pred) / sigma_pred * sigma_obs + mu_obs
  )
  1. Plot corrected and uncorrected temperatures together
# Plot the full dataset with adjusted x-axis limits
Plot <- ggplot() +
  geom_line(data = CR_85, aes(x = date, y = avg_temperature, color = "Predicted (Uncorrected)"), size = 1.2) +
  geom_line(data = CR_85, aes(x = date, y = corrected_temp, color = "Predicted (Corrected)"), size = 1.2, linetype = "dashed") +
  labs(
    title = "Original vs Corrected Predicted Temperatures - CR RCP 8.5",
    x = "Date",
    y = "Temperature (°C)",
    color = "Temperature Type"
  ) +
  scale_x_date(
    limits = as.Date(c("2012-01-01", "2020-12-01")), # Set x-axis limits
    date_labels = "%b %Y",
    date_breaks = "1 month",
    expand = c(0, 0)
  ) +
  scale_color_manual(values = c("Predicted (Uncorrected)" = "red", "Predicted (Corrected)" = "blue")) +
  theme_minimal() +
  theme(
    axis.text.x = element_text(angle = 45, hjust = 1),
    axis.title = element_text(size = 12),
    axis.text = element_text(size = 10),
    plot.title = element_text(size = 14, face = "bold"),
    legend.title = element_text(size = 12),
    legend.text = element_text(size = 10)
  )
Plot
Warning: Removed 960 rows containing missing values or values outside the scale range (`geom_line()`).
Warning: Removed 960 rows containing missing values or values outside the scale range (`geom_line()`).
ggsave("BiasCorrection/Geo_BiasCorrection/Plots/CorrectionComparison_CR85.jpeg", plot = Plot, width = 8, height = 6)
Warning: Removed 960 rows containing missing values or values outside the scale range (`geom_line()`).
Warning: Removed 960 rows containing missing values or values outside the scale range (`geom_line()`).

  1. Plot original versus corrected temperatures
# Plot the full dataset
Plot <- ggplot() +
  geom_line(data = CR_85, aes(x = date, y = avg_temperature, color = "Predicted (Uncorrected)"), size = 1.2) +
  geom_line(data = CR_85, aes(x = date, y = corrected_temp, color = "Predicted (Corrected)"), size = 1.2, linetype = "dashed") +
  geom_line(data = CRD_airport, aes(x = Date, y = Air_MonthAvg, color = "Observed"), size = 1.2) +
  labs(
    title = "Original vs Corrected Predicted Temperatures - CR RCP 8.5",
    x = "Date",
    y = "Temperature (°C)",
    color = "Temperature Type"
  ) +
  scale_x_date(
    date_labels = "%b %Y",
    date_breaks = "1 month",
    expand = c(0, 0)
  ) +
  scale_color_manual(values = c("Predicted (Uncorrected)" = "red", "Predicted (Corrected)" = "blue")) +
  theme_minimal() +
  theme(
    axis.text.x = element_text(angle = 45, hjust = 1),
    axis.title = element_text(size = 12),
    axis.text = element_text(size = 10),
    plot.title = element_text(size = 14, face = "bold"),
    legend.title = element_text(size = 12),
    legend.text = element_text(size = 10)
  )
Plot

ggsave("BiasCorrection/Geo_BiasCorrection/Plots/FullCorrection_CR85.jpeg", plot = Plot, width = 8, height = 6)

  1. Save the new file
# Save the corrected dataset to a CSV file
write.csv(CR_85, "BiasCorrection/Geo_BiasCorrection/DataFiles/SNAP_CR85_corrected_monthly.csv", row.names = FALSE)

Yakutat Foreland RCP 4.5

  1. Read in the data
# Read data files
YF_45 <- read.csv(file = "BiasCorrection/Geo_BiasCorrection/DataFiles/SNAP_YF45.csv") 
YF_45$date <- as.Date(YF_45$date,format="%Y-%m-%d")
YF_airport <- read.csv(file = "BiasCorrection/YF_PondAirTemp_mean.csv")
YF_airport <- YF_airport %>% select(-X)  # Remove unnecessary column 'X'
  1. Check dates
# Ensure that there are no NAs in the 'date' column after conversion
sum(is.na(YF_45$date))  # Check if there are any missing values (should be 0)
[1] 0
  1. Trim dates
# Trim YF_45 to the date range of YF_airport
start_date <- min(YF_airport$Date)
end_date <- max(YF_airport$Date)

# Subset YF_45 to match the date range of YF_airport
YF_45_trimmed <- YF_45 %>%
  filter(date >= start_date & date <= end_date)
  1. Plot pre-correction data
library(ggplot2)

# Ensure 'Date' in YF_airport is in Date format
YF_airport$Date <- as.Date(YF_airport$Date)

# Plot Observed vs Uncorrected Predicted Temperatures
Plot <- ggplot() +
  geom_line(data = YF_45_trimmed, aes(x = date, y = avg_temperature, color = "Predicted (Uncorrected)"), size = 1.2) +
  geom_line(data = YF_airport, aes(x = Date, y = Air_MonthAvg, color = "Observed"), size = 1.2) +
  geom_line(data = YF_airport, aes(x = Date, y = Air_MonthAvg, color = "Observed"), size = 1.2) +
  labs(
    title = "Observed vs Uncorrected Predicted Temperatures - YF 4.5",
    x = "Date",
    y = "Temperature (°C)",
    color = "Temperature Type"
  ) +
  scale_x_date(
    date_labels = "%b %Y",
    date_breaks = "1 month",
    expand = c(0, 0)
  ) +
  scale_color_manual(values = c("Predicted (Uncorrected)" = "red", "Observed" = "black")) +
  theme_minimal() +
  theme(
    axis.text.x = element_text(angle = 45, hjust = 1),
    axis.title = element_text(size = 12),
    axis.text = element_text(size = 10),
    plot.title = element_text(size = 14, face = "bold"),
    legend.title = element_text(size = 12),
    legend.text = element_text(size = 10)
  )
Plot

ggsave("BiasCorrection/Geo_BiasCorrection/Plots/Pre-CorrectionComparison_YF45.jpeg", plot = Plot, width = 8, height = 6)

  1. Monthly z-score bias correction
# Add "month" column for grouping
YF_45_trimmed$month <- format(YF_45_trimmed$date, "%m")
YF_airport$month <- format(YF_airport$Date, "%m")

# Calculate monthly means and standard deviations for observed and predicted temperatures
obs_monthly_stats <- YF_airport %>%
  group_by(month) %>%
  summarise(
    mu_obs = mean(Air_MonthAvg, na.rm = TRUE),
    sigma_obs = sd(Air_MonthAvg, na.rm = TRUE)
  )

pred_monthly_stats <- YF_45_trimmed %>%
  group_by(month) %>%
  summarise(
    mu_pred = mean(avg_temperature, na.rm = TRUE),
    sigma_pred = sd(avg_temperature, na.rm = TRUE)
  )

# Merge statistics back into the dataset
YF_45_trimmed <- YF_45_trimmed %>%
  left_join(obs_monthly_stats, by = "month") %>%
  left_join(pred_monthly_stats, by = "month")

# Apply bias correction
YF_45_trimmed <- YF_45_trimmed %>%
  mutate(
    corrected_temp = (avg_temperature - mu_pred) / sigma_pred * sigma_obs + mu_obs
  )
  1. Plot corrected data
# Plotting Observed vs Corrected Predicted Temperatures
Plot <- ggplot() +
  geom_line(data = YF_45_trimmed, aes(x = date, y = corrected_temp, color = "Predicted (Corrected)"), size = 1.2, linetype = "dashed") +
  geom_line(data = YF_airport, aes(x = Date, y = Air_MonthAvg, color = "Observed"), size = 1.2) +
  labs(
    title = "Observed vs Corrected Predicted Temperatures - YF RCP 4.5",
    x = "Date",
    y = "Temperature (°C)",
    color = "Temperature Type"
  ) +
  scale_x_date(
    date_labels = "%b %Y",
    date_breaks = "1 month",
    expand = c(0, 0)
  ) +
  scale_color_manual(values = c("Predicted (Corrected)" = "blue", "Observed" = "black")) +
  theme_minimal() +
  theme(
    axis.text.x = element_text(angle = 45, hjust = 1),
    axis.title = element_text(size = 12),
    axis.text = element_text(size = 10),
    plot.title = element_text(size = 14, face = "bold"),
    plot.subtitle = element_text(size = 12, face = "italic"),
    legend.title = element_text(size = 12),
    legend.text = element_text(size = 10)
  )
Plot

ggsave("BiasCorrection/Geo_BiasCorrection/Plots/Corrected_YF45.jpeg", plot = Plot, width = 8, height = 6)

  1. Correction applied to the whole dataset
# Add "month" column to the full dataset
YF_45$month <- format(YF_45$date, "%m")

# Merge monthly statistics into the full dataset
YF_45 <- YF_45 %>%
  left_join(obs_monthly_stats, by = "month") %>%
  left_join(pred_monthly_stats, by = "month")

# Apply the z-score bias correction
YF_45 <- YF_45 %>%
  mutate(
    corrected_temp = (avg_temperature - mu_pred) / sigma_pred * sigma_obs + mu_obs
  )
  1. Plot corrected and uncorrected temperatures together
# Plot the full dataset with adjusted x-axis limits
Plot <- ggplot() +
  geom_line(data = YF_45, aes(x = date, y = avg_temperature, color = "Predicted (Uncorrected)"), size = 1.2) +
  geom_line(data = YF_45, aes(x = date, y = corrected_temp, color = "Predicted (Corrected)"), size = 1.2, linetype = "dashed") +
  labs(
    title = "Original vs Corrected Predicted Temperatures - YF RCP 4.5",
    x = "Date",
    y = "Temperature (°C)",
    color = "Temperature Type"
  ) +
  scale_x_date(
    limits = as.Date(c("2012-01-01", "2020-12-01")), # Set x-axis limits
    date_labels = "%b %Y",
    date_breaks = "1 month",
    expand = c(0, 0)
  ) +
  scale_color_manual(values = c("Predicted (Uncorrected)" = "red", "Predicted (Corrected)" = "blue")) +
  theme_minimal() +
  theme(
    axis.text.x = element_text(angle = 45, hjust = 1),
    axis.title = element_text(size = 12),
    axis.text = element_text(size = 10),
    plot.title = element_text(size = 14, face = "bold"),
    legend.title = element_text(size = 12),
    legend.text = element_text(size = 10)
  )
Plot
Warning: Removed 960 rows containing missing values or values outside the scale range (`geom_line()`).
Warning: Removed 960 rows containing missing values or values outside the scale range (`geom_line()`).
ggsave("BiasCorrection/Geo_BiasCorrection/Plots/CorrectionComparison_YF45.jpeg", plot = Plot, width = 8, height = 6)
Warning: Removed 960 rows containing missing values or values outside the scale range (`geom_line()`).
Warning: Removed 960 rows containing missing values or values outside the scale range (`geom_line()`).

  1. Plot original versus corrected temperatures
# Plot the full dataset
Plot <- ggplot() +
  geom_line(data = YF_45, aes(x = date, y = avg_temperature, color = "Predicted (Uncorrected)"), size = 1.2) +
  geom_line(data = YF_45, aes(x = date, y = corrected_temp, color = "Predicted (Corrected)"), size = 1.2, linetype = "dashed") +
  geom_line(data = YF_airport, aes(x = Date, y = Air_MonthAvg, color = "Observed"), size = 1.2) +
  labs(
    title = "Original vs Corrected Predicted Temperatures - YF RCP 4.5",
    x = "Date",
    y = "Temperature (°C)",
    color = "Temperature Type"
  ) +
  scale_x_date(
    date_labels = "%b %Y",
    date_breaks = "1 month",
    expand = c(0, 0)
  ) +
  scale_color_manual(values = c("Predicted (Uncorrected)" = "red", "Predicted (Corrected)" = "blue")) +
  theme_minimal() +
  theme(
    axis.text.x = element_text(angle = 45, hjust = 1),
    axis.title = element_text(size = 12),
    axis.text = element_text(size = 10),
    plot.title = element_text(size = 14, face = "bold"),
    legend.title = element_text(size = 12),
    legend.text = element_text(size = 10)
  )
Plot

ggsave("BiasCorrection/Geo_BiasCorrection/Plots/FullCorrection_YF45.jpeg", plot = Plot, width = 8, height = 6)

  1. Save the new file
# Save the corrected dataset to a CSV file
write.csv(YF_45, "BiasCorrection/Geo_BiasCorrection/DataFiles/SNAP_YF45_corrected_monthly.csv", row.names = FALSE)

Yakutat Foreland RCP 8.5

  1. Read in the data
# Read data files
YF_85 <- read.csv(file = "BiasCorrection/Geo_BiasCorrection/DataFiles/SNAP_YF85.csv") 
YF_85$date <- as.Date(YF_85$date,format="%Y-%m-%d")
YF_airport <- read.csv(file = "BiasCorrection/YF_PondAirTemp_mean.csv")
YF_airport <- YF_airport %>% select(-X)  # Remove unnecessary column 'X'
  1. Check dates
# Ensure that there are no NAs in the 'date' column after conversion
sum(is.na(YF_85$date))  # Check if there are any missing values (should be 0)
[1] 0
  1. Trim dates
# Trim YF_85 to the date range of YF_airport
start_date <- min(YF_airport$Date)
end_date <- max(YF_airport$Date)

# Subset YF_85 to match the date range of YF_airport
YF_85_trimmed <- YF_85 %>%
  filter(date >= start_date & date <= end_date)
  1. Plot pre-correction data
library(ggplot2)

# Ensure 'Date' in YF_airport is in Date format
YF_airport$Date <- as.Date(YF_airport$Date)

# Plot Observed vs Uncorrected Predicted Temperatures
Plot <- ggplot() +
  geom_line(data = YF_85_trimmed, aes(x = date, y = avg_temperature, color = "Predicted (Uncorrected)"), size = 1.2) +
  geom_line(data = YF_airport, aes(x = Date, y = Air_MonthAvg, color = "Observed"), size = 1.2) +
  labs(
    title = "Observed vs Uncorrected Predicted Temperatures - YF 8.5",
    x = "Date",
    y = "Temperature (°C)",
    color = "Temperature Type"
  ) +
  scale_x_date(
    date_labels = "%b %Y",
    date_breaks = "1 month",
    expand = c(0, 0)
  ) +
  scale_color_manual(values = c("Predicted (Uncorrected)" = "red", "Observed" = "black")) +
  theme_minimal() +
  theme(
    axis.text.x = element_text(angle = 85, hjust = 1),
    axis.title = element_text(size = 12),
    axis.text = element_text(size = 10),
    plot.title = element_text(size = 14, face = "bold"),
    legend.title = element_text(size = 12),
    legend.text = element_text(size = 10)
  )
Plot

ggsave("BiasCorrection/Geo_BiasCorrection/Plots/Pre-CorrectionComparison_YF85.jpeg", plot = Plot, width = 8, height = 6)

  1. Monthly z-score bias correction
# Add "month" column for grouping
YF_85_trimmed$month <- format(YF_85_trimmed$date, "%m")
YF_airport$month <- format(YF_airport$Date, "%m")

# Calculate monthly means and standard deviations for observed and predicted temperatures
obs_monthly_stats <- YF_airport %>%
  group_by(month) %>%
  summarise(
    mu_obs = mean(Air_MonthAvg, na.rm = TRUE),
    sigma_obs = sd(Air_MonthAvg, na.rm = TRUE)
  )

pred_monthly_stats <- YF_85_trimmed %>%
  group_by(month) %>%
  summarise(
    mu_pred = mean(avg_temperature, na.rm = TRUE),
    sigma_pred = sd(avg_temperature, na.rm = TRUE)
  )

# Merge statistics back into the dataset
YF_85_trimmed <- YF_85_trimmed %>%
  left_join(obs_monthly_stats, by = "month") %>%
  left_join(pred_monthly_stats, by = "month")

# Apply bias correction
YF_85_trimmed <- YF_85_trimmed %>%
  mutate(
    corrected_temp = (avg_temperature - mu_pred) / sigma_pred * sigma_obs + mu_obs
  )
  1. Plot corrected data
# Plotting Observed vs Corrected Predicted Temperatures
Plot <- ggplot() +
  geom_line(data = YF_85_trimmed, aes(x = date, y = corrected_temp, color = "Predicted (Corrected)"), size = 1.2, linetype = "dashed") +
  geom_line(data = YF_airport, aes(x = Date, y = Air_MonthAvg, color = "Observed"), size = 1.2) +
  labs(
    title = "Observed vs Corrected Predicted Temperatures - YF RCP 8.5",
    x = "Date",
    y = "Temperature (°C)",
    color = "Temperature Type"
  ) +
  scale_x_date(
    date_labels = "%b %Y",
    date_breaks = "1 month",
    expand = c(0, 0)
  ) +
  scale_color_manual(values = c("Predicted (Corrected)" = "blue", "Observed" = "black")) +
  theme_minimal() +
  theme(
    axis.text.x = element_text(angle = 85, hjust = 1),
    axis.title = element_text(size = 12),
    axis.text = element_text(size = 10),
    plot.title = element_text(size = 14, face = "bold"),
    plot.subtitle = element_text(size = 12, face = "italic"),
    legend.title = element_text(size = 12),
    legend.text = element_text(size = 10)
  )
Plot

ggsave("BiasCorrection/Geo_BiasCorrection/Plots/Corrected_YF85.jpeg", plot = Plot, width = 8, height = 6)

  1. Correction applied to the whole dataset
# Add "month" column to the full dataset
YF_85$month <- format(YF_85$date, "%m")

# Merge monthly statistics into the full dataset
YF_85 <- YF_85 %>%
  left_join(obs_monthly_stats, by = "month") %>%
  left_join(pred_monthly_stats, by = "month")

# Apply the z-score bias correction
YF_85 <- YF_85 %>%
  mutate(
    corrected_temp = (avg_temperature - mu_pred) / sigma_pred * sigma_obs + mu_obs
  )
  1. Plot corrected and uncorrected temperatures together
# Plot the full dataset with adjusted x-axis limits
Plot <- ggplot() +
  geom_line(data = YF_85, aes(x = date, y = avg_temperature, color = "Predicted (Uncorrected)"), size = 1.2) +
  geom_line(data = YF_85, aes(x = date, y = corrected_temp, color = "Predicted (Corrected)"), size = 1.2, linetype = "dashed") +
  labs(
    title = "Original vs Corrected Predicted Temperatures - YF RCP 8.5",
    x = "Date",
    y = "Temperature (°C)",
    color = "Temperature Type"
  ) +
  scale_x_date(
    limits = as.Date(c("2012-01-01", "2020-12-01")), # Set x-axis limits
    date_labels = "%b %Y",
    date_breaks = "1 month",
    expand = c(0, 0)
  ) +
  scale_color_manual(values = c("Predicted (Uncorrected)" = "red", "Predicted (Corrected)" = "blue")) +
  theme_minimal() +
  theme(
    axis.text.x = element_text(angle = 45, hjust = 1),
    axis.title = element_text(size = 12),
    axis.text = element_text(size = 10),
    plot.title = element_text(size = 14, face = "bold"),
    legend.title = element_text(size = 12),
    legend.text = element_text(size = 10)
  )
Plot
Warning: Removed 960 rows containing missing values or values outside the scale range (`geom_line()`).
Warning: Removed 960 rows containing missing values or values outside the scale range (`geom_line()`).
ggsave("BiasCorrection/Geo_BiasCorrection/Plots/CorrectionComparison_YF85.jpeg", plot = Plot, width = 8, height = 6)
Warning: Removed 960 rows containing missing values or values outside the scale range (`geom_line()`).
Warning: Removed 960 rows containing missing values or values outside the scale range (`geom_line()`).

  1. Plot original versus corrected temperatures
# Plot the full dataset
Plot <- ggplot() +
  geom_line(data = YF_85, aes(x = date, y = avg_temperature, color = "Predicted (Uncorrected)"), size = 1.2) +
  geom_line(data = YF_85, aes(x = date, y = corrected_temp, color = "Predicted (Corrected)"), size = 1.2, linetype = "dashed") +
  geom_line(data = YF_airport, aes(x = Date, y = Air_MonthAvg, color = "Observed"), size = 1.2) +
  labs(
    title = "Original vs Corrected Predicted Temperatures - YF RCP 8.5",
    x = "Date",
    y = "Temperature (°C)",
    color = "Temperature Type"
  ) +
  scale_x_date(
    date_labels = "%b %Y",
    date_breaks = "1 month",
    expand = c(0, 0)
  ) +
  scale_color_manual(values = c("Predicted (Uncorrected)" = "red", "Predicted (Corrected)" = "blue")) +
  theme_minimal() +
  theme(
    axis.text.x = element_text(angle = 45, hjust = 1),
    axis.title = element_text(size = 12),
    axis.text = element_text(size = 10),
    plot.title = element_text(size = 14, face = "bold"),
    legend.title = element_text(size = 12),
    legend.text = element_text(size = 10)
  )
Plot

ggsave("BiasCorrection/Geo_BiasCorrection/Plots/FullCorrection_YF85.jpeg", plot = Plot, width = 8, height = 6)

  1. Save the new file
# Save the corrected dataset to a CSV file
write.csv(YF_85, "BiasCorrection/Geo_BiasCorrection/DataFiles/SNAP_YF85_corrected_monthly.csv", row.names = FALSE)
LS0tCnRpdGxlOiAiU05BUCBEYXRhIEV4dHJhY3Rpb24gYW5kIEJpYXMgQ29ycmVjdGlvbiAobW9udGhseSBjb3JyZWN0aW9uKSBGaWxlIgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKLS0tCgpTZXR0aW5nIHVwIHRoZSBkYXRhIHNvIHRoYXQgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiB0aGUgU05BUCBkYXRhIGFuZCB0aGUgYWlycG9ydCBzcGVjaWZpYyBkYXRhLgoKU3RlcCAxOiBFeHRyYWN0IHRoZSBSQ1AgU2l0ZSBkYXRhIGZyb20gdGhlIFNOQVAgNSBtb2RlbCBhdmVyYWdlcy4KClN0ZXAgMjogSW1wb3J0IGJvdGggZGF0YSBzZXRzCgpTdGVwIDM6IFNldCB1cCB0aGUgWi1zY29yZSBjYWxjdWxhdGlvbiBiYXNlZCBvbiBub3RlcyBmcm9tIG1lZXRpbmcgd2l0aCBBbGFuIEhhbWxldAoKU3RlcCA0OiBDYWxjdWxhdGUgdGhlIGF2ZXJhZ2UgYW5kIHN0YW5kYXJkIGRldmlhdGlvbiBvZiB0aGUgZGFpbHkgZGlmZmVyZW5jZXMKClN0ZXAgNSAobm90IGluIHRoaXMgZmlsZSk6IHJlcnVuIG1vZGVscyB3aXRoIHRoZSBuZXcgZm9yZWNhc3QgdGVtcGVyYXR1cmVzIC0tIExpc3QgdGhlc2UgZmlsZXMgaGVyZSBhZnRlciB0aGUgZmFjdCB0byBtYWtlIHN1cmUgdGhpcyBpcyB1cCB0byBkYXRlCgpMb2FkIGluIHRoZSBwYWNrYWdlcyBuZWVkZWQKCmBgYHtyfQpsaWJyYXJ5KGRwbHlyKQpgYGAKClNldHRpbmcgdXAgdGhlIHdvcmtzcGFjZQoKYGBge3J9CmxpYnJhcnkoZHBseXIpCmxpYnJhcnkoZ2dwbG90MikKCnNldHdkKCJ+L0xpYnJhcnkvQ2xvdWRTdG9yYWdlL0Ryb3Bib3gvU1dFTC9Db3BwZXJSaXZlckRlbHRhL1BvbmRUZW1wcy9EYXRhQW5hbHlzaXMvUG9uZFRlbXBzQW5hbHlzaXMiKQpgYGAKCiMgRXh0cmFjdGluZyB0aGUgUkNQIGRhdGEgZnJvbSB0aGUgYWF0IGZpbGUKCiMjIFJlYWQgaW4gdGhlIGRhdGEKCmBgYHtyfQpsb2FkKCJ+L0Ryb3Bib3gvU1dFTC9Db3BwZXJSaXZlckRlbHRhL1BvbmRUZW1wcy9EYXRhQW5hbHlzaXMvUG9uZFRlbXBzQW5hbHlzaXMvZm9yZWNhc3RlZF90ZW1wZXJhdHVyZS5SRGF0YSIpCgpzdHIoYWF0KQpgYGAKVGhpcyBjb21lcyBpbiBhcyBhIGRhdGFmaWxlIHdpdGggY29sdW1ucyB0ZW1wZXJhdHVyZSwgcmNwLCBtb2RlbCwgbW9udGgsIHllYXIsIHNpdGUsIGFuZCBkYXRlCgojIyBFeHRyYWN0IHRoZSBkYXRhCgpgYGB7cn0KIyBzZWxlY3RpbmcgQ1JECkNSRCA8LSBhYXQgJT4lCiAgZHBseXI6OmZpbHRlcihzaXRlID09ICJjb3JkIikKCiMgZmlsdGVyIGZvciBlYWNoIHJjcApDUl80LjUgPC0gQ1JEICU+JQogIGRwbHlyOjpmaWx0ZXIocmNwID09ICI0NSIpCgpDUl82LjAgPC0gQ1JEICU+JQogIGRwbHlyOjpmaWx0ZXIocmNwID09ICI2MCIpCgpDUl84LjUgPC0gQ1JEICU+JQogIGRwbHlyOjpmaWx0ZXIocmNwID09ICI4NSIpCgojIHNlbGVjdGluZyBZRgpZRiA8LSBhYXQgJT4lCiAgZHBseXI6OmZpbHRlcihzaXRlID09ICJ5YWsiKQoKIyBmaWx0ZXIgZm9yIGVhY2ggcmNwCllGXzQuNSA8LSBZRiAlPiUKICBkcGx5cjo6ZmlsdGVyKHJjcCA9PSAiNDUiKQoKWUZfNi4wIDwtIFlGICU+JQogIGRwbHlyOjpmaWx0ZXIocmNwID09ICI2MCIpCgpZRl84LjUgPC0gWUYlPiUKICBkcGx5cjo6ZmlsdGVyKHJjcCA9PSAiODUiKQpgYGAKCgpgYGB7cn0KZ2dwbG90KCkrCiAgIGdlb21fc21vb3RoKGRhdGEgPSBDUl84LjUsIGFlcyh4ID0gZGF0ZSwgeSA9IHRlbXBlcmF0dXJlLCBjb2xvciA9ICJyZWQiKSkgKwogICBnZW9tX3Ntb290aChkYXRhID0gQ1JfNC41LCBhZXMoeCA9IGRhdGUsIHkgPSB0ZW1wZXJhdHVyZSwgY29sb3IgPSAiYmx1ZSIpKQogCgoKYGBgCgojIyBTdGFydGluZyB3aXRoIHRoZSBSQ1AgNC41IGRhdGEgCgojIyMgRmlsdGVyaW5nIHRvIDQuNQpgYGB7cn0KQ1JfNC41CgpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KHpvbykKCiMgQ29udmVydCB0aGUgJ3llYXJtb24nIG51bWVyaWMgZGF0ZSB0byBhIHByb3BlciBEYXRlIG9iamVjdCAoZmlyc3QgZGF5IG9mIGVhY2ggbW9udGgpCkNSXzQuNSRkYXRlIDwtIGFzLkRhdGUoYXMueWVhcm1vbihDUl80LjUkZGF0ZSksIGZyYWMgPSAwKQoKIyBHcm91cCBieSBkYXRlICh5ZWFyIGFuZCBtb250aCBjb21iaW5hdGlvbikgYW5kIGNhbGN1bGF0ZSBhdmVyYWdlIHRlbXBlcmF0dXJlCmF2Z19DUl80LjUgPC0gQ1JfNC41ICU+JQogIGdyb3VwX2J5KGRhdGUpICU+JQogIHN1bW1hcmlzZShhdmdfdGVtcGVyYXR1cmUgPSBtZWFuKHRlbXBlcmF0dXJlLCBuYS5ybSA9IFRSVUUpLAogICAgICAgICAgICBzdGRfdGVtcGVyYXR1cmUgPSBzZCh0ZW1wZXJhdHVyZSwgbmEucm0gPSBUUlVFKSwKICAgICAgICAgICAgcHJlY2lzaW9uID0gMSAvIChzZCh0ZW1wZXJhdHVyZSwgbmEucm0gPSBUUlVFKV4yKSkKCiMgVmlldyB0aGUgcmVzdWx0aW5nIGRhdGFmcmFtZQpwcmludChhdmdfQ1JfNC41KQoKQ1JfNC41IDwtIGF2Z19DUl80LjUKQ1JfNC41CmBgYAoKCmBgYHtyfQpZRl80LjUKIyBDb252ZXJ0IHRoZSAneWVhcm1vbicgbnVtZXJpYyBkYXRlIHRvIGEgcHJvcGVyIERhdGUgb2JqZWN0IChmaXJzdCBkYXkgb2YgZWFjaCBtb250aCkKWUZfNC41JGRhdGUgPC0gYXMuRGF0ZShhcy55ZWFybW9uKFlGXzQuNSRkYXRlKSwgZnJhYyA9IDApCgojIEdyb3VwIGJ5IGRhdGUgKHllYXIgYW5kIG1vbnRoIGNvbWJpbmF0aW9uKSBhbmQgY2FsY3VsYXRlIGF2ZXJhZ2UgdGVtcGVyYXR1cmUKYXZnX1lGXzQuNSA8LSBZRl80LjUgJT4lCiAgZ3JvdXBfYnkoZGF0ZSkgJT4lCiAgc3VtbWFyaXNlKGF2Z190ZW1wZXJhdHVyZSA9IG1lYW4odGVtcGVyYXR1cmUsIG5hLnJtID0gVFJVRSksCiAgICAgICAgICAgIHN0ZF90ZW1wZXJhdHVyZSA9IHNkKHRlbXBlcmF0dXJlLCBuYS5ybSA9IFRSVUUpLAogICAgICAgICAgICBwcmVjaXNpb24gPSAxIC8gKHNkKHRlbXBlcmF0dXJlLCBuYS5ybSA9IFRSVUUpXjIpKQoKIyBWaWV3IHRoZSByZXN1bHRpbmcgZGF0YWZyYW1lCnByaW50KGF2Z19ZRl80LjUpCgpZRl80LjUgPC0gYXZnX1lGXzQuNQpZRl80LjUKYGBgCgojIyMgUGxvdCB0aGUgZm9yZWNhc3RlZCBkYXRhCgpgYGB7cn0KQ1JfNC41CgojIEZ1bGwgdGltZSBmcmFtZSAoMjAwNi0yMTAwKQpDUl9TTkFQIDwtIGdncGxvdChkYXRhID0gQ1JfNC41LCBtYXBwaW5nID0gYWVzKHggPSBkYXRlKSkgKwogIGdlb21fbGluZShhZXMoeSA9IGF2Z190ZW1wZXJhdHVyZSksIHNpemUgPSAwLjgpICsgICMgTGluZSBwbG90IGZvciBhdmdfdGVtcGVyYXR1cmUKICBnZW9tX3JpYmJvbihhZXMoeW1pbiA9IGF2Z190ZW1wZXJhdHVyZSAtIHN0ZF90ZW1wZXJhdHVyZSwgCiAgICAgICAgICAgICAgICAgIHltYXggPSBhdmdfdGVtcGVyYXR1cmUgKyBzdGRfdGVtcGVyYXR1cmUpLCAgIyBSaWJib24gZm9yIHVuY2VydGFpbnR5CiAgICAgICAgICAgICAgYWxwaGEgPSAwLjUsIGZpbGwgPSAiYmx1ZSIpICsKICB4bGFiKCJZZWFyIikgKwogIHlsYWIoIk1lYW4gRm9yZWNhc3QgVGVtcGVyYXR1cmUiKSArCiAgZ2d0aXRsZSgiQ29wcGVyIFJpdmVyIFNOQVAgRm9yZWNhc3QgLSBSQ1AgNC41IikgKwogIHRoZW1lX2NsYXNzaWMoKSArCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpCkNSX1NOQVAKCgpnZ3NhdmUoIkNSX0dlb19Gb3JlY2FzdDQuNV8yMDIwLmpwZWciLCBwbG90ID0gQ1JfU05BUCwgd2lkdGggPSA4LCBoZWlnaHQgPSA2KQpgYGAKCgpgYGB7cn0KWUZfNC41CgojIEZ1bGwgdGltZSBmcmFtZSAoMjAwNi0yMTAwKQpZRl9TTkFQIDwtIGdncGxvdChkYXRhID0gWUZfNC41LCBtYXBwaW5nID0gYWVzKHggPSBkYXRlKSkgKwogIGdlb21fbGluZShhZXMoeSA9IGF2Z190ZW1wZXJhdHVyZSksIHNpemUgPSAwLjgpICsgICMgTGluZSBwbG90IGZvciBhdmdfdGVtcGVyYXR1cmUKICBnZW9tX3JpYmJvbihhZXMoeW1pbiA9IGF2Z190ZW1wZXJhdHVyZSAtIHN0ZF90ZW1wZXJhdHVyZSwKICAgICAgICAgICAgICAgICAgeW1heCA9IGF2Z190ZW1wZXJhdHVyZSArIHN0ZF90ZW1wZXJhdHVyZSksICAjIFJpYmJvbiBmb3IgdW5jZXJ0YWludHkKICAgICAgICAgICAgICBhbHBoYSA9IDAuNSwgZmlsbCA9ICJibHVlIikgKwogIHhsYWIoIlllYXIiKSArCiAgeWxhYigiTWVhbiBGb3JlY2FzdCBUZW1wZXJhdHVyZSIpICsKICBnZ3RpdGxlKCJZYWt1dGF0IEZvcmVsYW5kIFNOQVAgRm9yZWNhc3QgLSBSQ1AgNC41IikgKwogIHRoZW1lX2NsYXNzaWMoKSArCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpCllGX1NOQVAKCgpnZ3NhdmUoIllGX0dlb19Gb3JlY2FzdDQuNV8yMDIwLmpwZWciLCBwbG90ID0gWUZfU05BUCwgd2lkdGggPSA4LCBoZWlnaHQgPSA2KQpgYGAKCiMjIENvbnRpbnVpbmcgd2l0aCB0aGUgUkNQIDYuMCBkYXRhCgojIyMgRmlsdGVyaW5nIHRvIDYuMApgYGB7cn0KQ1JfNi4wCgojIENvbnZlcnQgdGhlICd5ZWFybW9uJyBudW1lcmljIGRhdGUgdG8gYSBwcm9wZXIgRGF0ZSBvYmplY3QgKGZpcnN0IGRheSBvZiBlYWNoIG1vbnRoKQpDUl82LjAkZGF0ZSA8LSBhcy5EYXRlKGFzLnllYXJtb24oQ1JfNi4wJGRhdGUpLCBmcmFjID0gMCkKCiMgR3JvdXAgYnkgZGF0ZSAoeWVhciBhbmQgbW9udGggY29tYmluYXRpb24pIGFuZCBjYWxjdWxhdGUgYXZlcmFnZSB0ZW1wZXJhdHVyZQphdmdfQ1JfNi4wIDwtIENSXzYuMCAlPiUKICBncm91cF9ieShkYXRlKSAlPiUKICBzdW1tYXJpc2UoYXZnX3RlbXBlcmF0dXJlID0gbWVhbih0ZW1wZXJhdHVyZSwgbmEucm0gPSBUUlVFKSwKICAgICAgICAgICAgc3RkX3RlbXBlcmF0dXJlID0gc2QodGVtcGVyYXR1cmUsIG5hLnJtID0gVFJVRSksCiAgICAgICAgICAgIHByZWNpc2lvbiA9IDEgLyAoc2QodGVtcGVyYXR1cmUsIG5hLnJtID0gVFJVRSleMikpCgojIFZpZXcgdGhlIHJlc3VsdGluZyBkYXRhZnJhbWUKcHJpbnQoYXZnX0NSXzYuMCkKCkNSXzYuMCA8LSBhdmdfQ1JfNi4wCkNSXzYuMApgYGAKCgpgYGB7cn0KWUZfNi4wCgojIENvbnZlcnQgdGhlICd5ZWFybW9uJyBudW1lcmljIGRhdGUgdG8gYSBwcm9wZXIgRGF0ZSBvYmplY3QgKGZpcnN0IGRheSBvZiBlYWNoIG1vbnRoKQpZRl82LjAkZGF0ZSA8LSBhcy5EYXRlKGFzLnllYXJtb24oWUZfNi4wJGRhdGUpLCBmcmFjID0gMCkKCiMgR3JvdXAgYnkgZGF0ZSAoeWVhciBhbmQgbW9udGggY29tYmluYXRpb24pIGFuZCBjYWxjdWxhdGUgYXZlcmFnZSB0ZW1wZXJhdHVyZQphdmdfWUZfNi4wIDwtIFlGXzYuMCAlPiUKICBncm91cF9ieShkYXRlKSAlPiUKICBzdW1tYXJpc2UoYXZnX3RlbXBlcmF0dXJlID0gbWVhbih0ZW1wZXJhdHVyZSwgbmEucm0gPSBUUlVFKSwKICAgICAgICAgICAgc3RkX3RlbXBlcmF0dXJlID0gc2QodGVtcGVyYXR1cmUsIG5hLnJtID0gVFJVRSksCiAgICAgICAgICAgIHByZWNpc2lvbiA9IDEgLyAoc2QodGVtcGVyYXR1cmUsIG5hLnJtID0gVFJVRSleMikpCgojIFZpZXcgdGhlIHJlc3VsdGluZyBkYXRhZnJhbWUKcHJpbnQoYXZnX1lGXzYuMCkKCllGXzYuMCA8LSBhdmdfWUZfNi4wCllGXzYuMApgYGAKCiMjIyBQbG90IHRoZSBmb3JlY2FzdGVkIGRhdGEKCmBgYHtyfQpDUl82LjAKCiMgRnVsbCB0aW1lIGZyYW1lICgyMDA2LTIxMDApCkNSX1NOQVAgPC0gZ2dwbG90KGRhdGEgPSBDUl82LjAsIG1hcHBpbmcgPSBhZXMoeCA9IGRhdGUpKSArCiAgZ2VvbV9saW5lKGFlcyh5ID0gYXZnX3RlbXBlcmF0dXJlKSwgc2l6ZSA9IDAuOCkgKyAgIyBMaW5lIHBsb3QgZm9yIGF2Z190ZW1wZXJhdHVyZQogIGdlb21fcmliYm9uKGFlcyh5bWluID0gYXZnX3RlbXBlcmF0dXJlIC0gc3RkX3RlbXBlcmF0dXJlLCAKICAgICAgICAgICAgICAgICAgeW1heCA9IGF2Z190ZW1wZXJhdHVyZSArIHN0ZF90ZW1wZXJhdHVyZSksICAjIFJpYmJvbiBmb3IgdW5jZXJ0YWludHkKICAgICAgICAgICAgICBhbHBoYSA9IDAuNSwgZmlsbCA9ICJibHVlIikgKwogIHhsYWIoIlllYXIiKSArCiAgeWxhYigiTWVhbiBGb3JlY2FzdCBUZW1wZXJhdHVyZSIpICsKICBnZ3RpdGxlKCJDb3BwZXIgUml2ZXIgU05BUCBGb3JlY2FzdCAtIFJDUCA2LjAiKSArCiAgdGhlbWVfY2xhc3NpYygpICsKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkKQ1JfU05BUAoKCmdnc2F2ZSgiQ1JfR2VvX0ZvcmVjYXN0Ni4wXzIwMjAuanBlZyIsIHBsb3QgPSBDUl9TTkFQLCB3aWR0aCA9IDgsIGhlaWdodCA9IDYpCmBgYAoKYGBge3J9CllGXzYuMAoKIyBGdWxsIHRpbWUgZnJhbWUgKDIwMDYtMjEwMCkKWUZfU05BUCA8LSBnZ3Bsb3QoZGF0YSA9IFlGXzYuMCwgbWFwcGluZyA9IGFlcyh4ID0gZGF0ZSkpICsKICBnZW9tX2xpbmUoYWVzKHkgPSBhdmdfdGVtcGVyYXR1cmUpLCBzaXplID0gMC44KSArICAjIExpbmUgcGxvdCBmb3IgYXZnX3RlbXBlcmF0dXJlCiAgZ2VvbV9yaWJib24oYWVzKHltaW4gPSBhdmdfdGVtcGVyYXR1cmUgLSBzdGRfdGVtcGVyYXR1cmUsCiAgICAgICAgICAgICAgICAgIHltYXggPSBhdmdfdGVtcGVyYXR1cmUgKyBzdGRfdGVtcGVyYXR1cmUpLCAgIyBSaWJib24gZm9yIHVuY2VydGFpbnR5CiAgICAgICAgICAgICAgYWxwaGEgPSAwLjUsIGZpbGwgPSAiYmx1ZSIpICsKICB4bGFiKCJZZWFyIikgKwogIHlsYWIoIk1lYW4gRm9yZWNhc3QgVGVtcGVyYXR1cmUiKSArCiAgZ2d0aXRsZSgiWWFrdXRhdCBGb3JlbGFuZCBTTkFQIEZvcmVjYXN0IC0gUkNQIDYuMCIpICsKICB0aGVtZV9jbGFzc2ljKCkgKwogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpKQpZRl9TTkFQCgoKZ2dzYXZlKCJZRl9HZW9fRm9yZWNhc3Q2LjBfMjAyMC5qcGVnIiwgcGxvdCA9IFlGX1NOQVAsIHdpZHRoID0gOCwgaGVpZ2h0ID0gNikKYGBgCgojIyBDb250aW51aW5nIHdpdGggdGhlIFJDUCA4LjUgZGF0YQoKIyMjIEZpbHRlcmluZyB0byA4LjUKYGBge3J9CkNSXzguNQoKIyBDb252ZXJ0IHRoZSAneWVhcm1vbicgbnVtZXJpYyBkYXRlIHRvIGEgcHJvcGVyIERhdGUgb2JqZWN0IChmaXJzdCBkYXkgb2YgZWFjaCBtb250aCkKQ1JfOC41JGRhdGUgPC0gYXMuRGF0ZShhcy55ZWFybW9uKENSXzguNSRkYXRlKSwgZnJhYyA9IDApCgojIEdyb3VwIGJ5IGRhdGUgKHllYXIgYW5kIG1vbnRoIGNvbWJpbmF0aW9uKSBhbmQgY2FsY3VsYXRlIGF2ZXJhZ2UgdGVtcGVyYXR1cmUKYXZnX0NSXzguNSA8LSBDUl84LjUgJT4lCiAgZ3JvdXBfYnkoZGF0ZSkgJT4lCiAgc3VtbWFyaXNlKGF2Z190ZW1wZXJhdHVyZSA9IG1lYW4odGVtcGVyYXR1cmUsIG5hLnJtID0gVFJVRSksCiAgICAgICAgICAgIHN0ZF90ZW1wZXJhdHVyZSA9IHNkKHRlbXBlcmF0dXJlLCBuYS5ybSA9IFRSVUUpLAogICAgICAgICAgICBwcmVjaXNpb24gPSAxIC8gKHNkKHRlbXBlcmF0dXJlLCBuYS5ybSA9IFRSVUUpXjIpKQoKIyBWaWV3IHRoZSByZXN1bHRpbmcgZGF0YWZyYW1lCnByaW50KGF2Z19DUl84LjUpCgpDUl84LjUgPC0gYXZnX0NSXzguNQpDUl84LjUKYGBgCgoKYGBge3J9CllGXzguNQoKIyBDb252ZXJ0IHRoZSAneWVhcm1vbicgbnVtZXJpYyBkYXRlIHRvIGEgcHJvcGVyIERhdGUgb2JqZWN0IChmaXJzdCBkYXkgb2YgZWFjaCBtb250aCkKWUZfOC41JGRhdGUgPC0gYXMuRGF0ZShhcy55ZWFybW9uKFlGXzguNSRkYXRlKSwgZnJhYyA9IDApCgojIEdyb3VwIGJ5IGRhdGUgKHllYXIgYW5kIG1vbnRoIGNvbWJpbmF0aW9uKSBhbmQgY2FsY3VsYXRlIGF2ZXJhZ2UgdGVtcGVyYXR1cmUKYXZnX1lGXzguNSA8LSBZRl84LjUgJT4lCiAgZ3JvdXBfYnkoZGF0ZSkgJT4lCiAgc3VtbWFyaXNlKGF2Z190ZW1wZXJhdHVyZSA9IG1lYW4odGVtcGVyYXR1cmUsIG5hLnJtID0gVFJVRSksCiAgICAgICAgICAgIHN0ZF90ZW1wZXJhdHVyZSA9IHNkKHRlbXBlcmF0dXJlLCBuYS5ybSA9IFRSVUUpLAogICAgICAgICAgICBwcmVjaXNpb24gPSAxIC8gKHNkKHRlbXBlcmF0dXJlLCBuYS5ybSA9IFRSVUUpXjIpKQoKIyBWaWV3IHRoZSByZXN1bHRpbmcgZGF0YWZyYW1lCnByaW50KGF2Z19ZRl84LjUpCgpZRl84LjUgPC0gYXZnX1lGXzguNQpZRl84LjUKYGBgCgojIyMgUGxvdCB0aGUgZm9yZWNhc3RlZCBkYXRhCgpgYGB7cn0KQ1JfOC41CgojIEZ1bGwgdGltZSBmcmFtZSAoMjAwNi0yMTAwKQpDUl9TTkFQIDwtIGdncGxvdChkYXRhID0gQ1JfOC41LCBtYXBwaW5nID0gYWVzKHggPSBkYXRlKSkgKwogIGdlb21fbGluZShhZXMoeSA9IGF2Z190ZW1wZXJhdHVyZSksIHNpemUgPSAwLjgpICsgICMgTGluZSBwbG90IGZvciBhdmdfdGVtcGVyYXR1cmUKICBnZW9tX3JpYmJvbihhZXMoeW1pbiA9IGF2Z190ZW1wZXJhdHVyZSAtIHN0ZF90ZW1wZXJhdHVyZSwgCiAgICAgICAgICAgICAgICAgIHltYXggPSBhdmdfdGVtcGVyYXR1cmUgKyBzdGRfdGVtcGVyYXR1cmUpLCAgIyBSaWJib24gZm9yIHVuY2VydGFpbnR5CiAgICAgICAgICAgICAgYWxwaGEgPSAwLjUsIGZpbGwgPSAiYmx1ZSIpICsKICB4bGFiKCJZZWFyIikgKwogIHlsYWIoIk1lYW4gRm9yZWNhc3QgVGVtcGVyYXR1cmUiKSArCiAgZ2d0aXRsZSgiQ29wcGVyIFJpdmVyIFNOQVAgRm9yZWNhc3QgLSBSQ1AgOC41IikgKwogIHRoZW1lX2NsYXNzaWMoKSArCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpCkNSX1NOQVAKCgpnZ3NhdmUoIkNSX0dlb19Gb3JlY2FzdDguNV8yMDIwLmpwZWciLCBwbG90ID0gQ1JfU05BUCwgd2lkdGggPSA4LCBoZWlnaHQgPSA2KQpgYGAKCmBgYHtyfQpZRl84LjUKCiMgRnVsbCB0aW1lIGZyYW1lICgyMDA2LTIxMDApCllGX1NOQVAgPC0gZ2dwbG90KGRhdGEgPSBZRl84LjUsIG1hcHBpbmcgPSBhZXMoeCA9IGRhdGUpKSArCiAgZ2VvbV9saW5lKGFlcyh5ID0gYXZnX3RlbXBlcmF0dXJlKSwgc2l6ZSA9IDAuOCkgKyAgIyBMaW5lIHBsb3QgZm9yIGF2Z190ZW1wZXJhdHVyZQogIGdlb21fcmliYm9uKGFlcyh5bWluID0gYXZnX3RlbXBlcmF0dXJlIC0gc3RkX3RlbXBlcmF0dXJlLAogICAgICAgICAgICAgICAgICB5bWF4ID0gYXZnX3RlbXBlcmF0dXJlICsgc3RkX3RlbXBlcmF0dXJlKSwgICMgUmliYm9uIGZvciB1bmNlcnRhaW50eQogICAgICAgICAgICAgIGFscGhhID0gMC41LCBmaWxsID0gImJsdWUiKSArCiAgeGxhYigiWWVhciIpICsKICB5bGFiKCJNZWFuIEZvcmVjYXN0IFRlbXBlcmF0dXJlIikgKwogIGdndGl0bGUoIllha3V0YXQgRm9yZWxhbmQgU05BUCBGb3JlY2FzdCAtIFJDUCA4LjUiKSArCiAgdGhlbWVfY2xhc3NpYygpICsKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkKWUZfU05BUAoKCmdnc2F2ZSgiWUZfR2VvX0ZvcmVjYXN0OC41XzIwMjAuanBlZyIsIHBsb3QgPSBZRl9TTkFQLCB3aWR0aCA9IDgsIGhlaWdodCA9IDYpCmBgYAoKU2F2aW5nIHRoZSBkYXRhIGFzIGRhdGFmaWxlcyBmb3IgbGF0ZXIgdXNlCgpgYGB7cn0Kd3JpdGUuY3N2KFlGXzQuNSwgZmlsZSA9ICJCaWFzQ29ycmVjdGlvbi9HZW9fQmlhc0NvcnJlY3Rpb24vRGF0YUZpbGVzL1NOQVBfWUY0NS5jc3YiLCByb3cubmFtZXMgPSBGQUxTRSkKd3JpdGUuY3N2KFlGXzYuMCwgZmlsZSA9ICJCaWFzQ29ycmVjdGlvbi9HZW9fQmlhc0NvcnJlY3Rpb24vRGF0YUZpbGVzL1NOQVBfWUY2MC5jc3YiLCByb3cubmFtZXMgPSBGQUxTRSkKd3JpdGUuY3N2KFlGXzguNSwgZmlsZSA9ICJCaWFzQ29ycmVjdGlvbi9HZW9fQmlhc0NvcnJlY3Rpb24vRGF0YUZpbGVzL1NOQVBfWUY4NS5jc3YiLCByb3cubmFtZXMgPSBGQUxTRSkKCndyaXRlLmNzdihDUl80LjUsIGZpbGUgPSAiQmlhc0NvcnJlY3Rpb24vR2VvX0JpYXNDb3JyZWN0aW9uL0RhdGFGaWxlcy9TTkFQX0NSNDUuY3N2Iiwgcm93Lm5hbWVzID0gRkFMU0UpCndyaXRlLmNzdihDUl82LjAsIGZpbGUgPSAiQmlhc0NvcnJlY3Rpb24vR2VvX0JpYXNDb3JyZWN0aW9uL0RhdGFGaWxlcy9TTkFQX0NSNjAuY3N2Iiwgcm93Lm5hbWVzID0gRkFMU0UpCndyaXRlLmNzdihDUl84LjUsIGZpbGUgPSAiQmlhc0NvcnJlY3Rpb24vR2VvX0JpYXNDb3JyZWN0aW9uL0RhdGFGaWxlcy9TTkFQX0NSODUuY3N2Iiwgcm93Lm5hbWVzID0gRkFMU0UpCmBgYAoKSWYgdGhlc2UgYWJvdmUgaXMgYWxyZWFkeSBkb25lLCBzdGFydCBoZXJlIGFuZCBqdXN0IHJlYWQgaW4gdGhlIGZpbGVzIHRoYXQgd2VyZSBjcmVhdGVkIF4KYGBge3J9CllGXzQ1IDwtIHJlYWQuY3N2KGZpbGUgPSAiQmlhc0NvcnJlY3Rpb24vR2VvX0JpYXNDb3JyZWN0aW9uL0RhdGFGaWxlcy9TTkFQX1lGNDUuY3N2IikgCllGXzQ1JGRhdGUgPC0gYXMuRGF0ZShZRl80NSRkYXRlLGZvcm1hdD0iJVktJW0tJWQiKQpZRl84NSA8LSByZWFkLmNzdihmaWxlID0gIkJpYXNDb3JyZWN0aW9uL0dlb19CaWFzQ29ycmVjdGlvbi9EYXRhRmlsZXMvU05BUF9ZRjg1LmNzdiIpCllGXzg1JGRhdGUgPC0gYXMuRGF0ZShZRl84NSRkYXRlLGZvcm1hdD0iJVktJW0tJWQiKQoKQ1JfNDUgPC0gcmVhZC5jc3YoZmlsZSA9ICJCaWFzQ29ycmVjdGlvbi9HZW9fQmlhc0NvcnJlY3Rpb24vRGF0YUZpbGVzL1NOQVBfQ1I0NS5jc3YiKQpDUl80NSRkYXRlIDwtIGFzLkRhdGUoQ1JfNDUkZGF0ZSxmb3JtYXQ9IiVZLSVtLSVkIikKQ1JfODUgPC0gcmVhZC5jc3YoZmlsZSA9ICJCaWFzQ29ycmVjdGlvbi9HZW9fQmlhc0NvcnJlY3Rpb24vRGF0YUZpbGVzL1NOQVBfQ1I4NS5jc3YiKQpDUl84NSRkYXRlIDwtIGFzLkRhdGUoQ1JfODUkZGF0ZSxmb3JtYXQ9IiVZLSVtLSVkIikKYGBgCgpSZWFkIGluIHRoZSBkYXRhIGZpbGUgZm9yIHRoZSBhaXJwb3J0IHRlbXBlcmF0dXJlIGRhdGEKICBTZXBhcmF0ZSB0aGlzIGJ5IGFpcnBvcnQgbG9jYXRpb24KCmBgYHtyfQpDUkRfYWlycG9ydCA8LSByZWFkLmNzdihmaWxlID0gIkJpYXNDb3JyZWN0aW9uL0NSX1BvbmRBaXJUZW1wX21lYW4uY3N2IikKQ1JEX2FpcnBvcnQgPC0gQ1JEX2FpcnBvcnQgJT4lCiAgc2VsZWN0KC1YKQoKWUZfYWlycG9ydCA8LSByZWFkLmNzdihmaWxlID0gIkJpYXNDb3JyZWN0aW9uL1lGX1BvbmRBaXJUZW1wX21lYW4uY3N2IikKWUZfYWlycG9ydCA8LSBZRl9haXJwb3J0ICU+JQogIHNlbGVjdCgtWCkKYGBgCgojIENvcHBlciBSaXZlciBEZWx0YSBSQ1AgNC41CgoxLiBSZWFkIGluIHRoZSBkYXRhCmBgYHtyfQojIFJlYWQgZGF0YSBmaWxlcwpDUl80NSA8LSByZWFkLmNzdihmaWxlID0gIkJpYXNDb3JyZWN0aW9uL0dlb19CaWFzQ29ycmVjdGlvbi9EYXRhRmlsZXMvU05BUF9DUjQ1LmNzdiIpIApDUl80NSRkYXRlIDwtIGFzLkRhdGUoQ1JfNDUkZGF0ZSxmb3JtYXQ9IiVZLSVtLSVkIikKQ1JEX2FpcnBvcnQgPC0gcmVhZC5jc3YoZmlsZSA9ICJCaWFzQ29ycmVjdGlvbi9DUl9Qb25kQWlyVGVtcF9tZWFuLmNzdiIpCkNSRF9haXJwb3J0JERhdGUgPC0gYXMuRGF0ZShDUkRfYWlycG9ydCREYXRlLCBmb3JtYXQgPSAiJVktJW0tJWQiKQpDUkRfYWlycG9ydCA8LSBDUkRfYWlycG9ydCAlPiUgc2VsZWN0KC1YKSAgIyBSZW1vdmUgdW5uZWNlc3NhcnkgY29sdW1uICdYJwoKYGBgCgoyLiBDaGVjayBkYXRlcwoKYGBge3J9CiMgRW5zdXJlIHRoYXQgdGhlcmUgYXJlIG5vIE5BcyBpbiB0aGUgJ2RhdGUnIGNvbHVtbiBhZnRlciBjb252ZXJzaW9uCnN1bShpcy5uYShDUl80NSRkYXRlKSkgICMgQ2hlY2sgaWYgdGhlcmUgYXJlIGFueSBtaXNzaW5nIHZhbHVlcyAoc2hvdWxkIGJlIDApCgpgYGAKCjMuIFRyaW0gZGF0ZXMKCmBgYHtyfQojIFRyaW0gQ1JfNDUgdG8gdGhlIGRhdGUgcmFuZ2Ugb2YgQ1JEX2FpcnBvcnQKc3RhcnRfZGF0ZSA8LSBtaW4oQ1JEX2FpcnBvcnQkRGF0ZSkKZW5kX2RhdGUgPC0gbWF4KENSRF9haXJwb3J0JERhdGUpCgojIFN1YnNldCBDUl80NSB0byBtYXRjaCB0aGUgZGF0ZSByYW5nZSBvZiBDUkRfYWlycG9ydApDUl80NV90cmltbWVkIDwtIENSXzQ1ICU+JQogIGZpbHRlcihkYXRlID49IHN0YXJ0X2RhdGUgJiBkYXRlIDw9IGVuZF9kYXRlKQoKYGBgCgo0LiBQbG90IHByZS1jb3JyZWN0aW9uIGRhdGEKCmBgYHtyfQpsaWJyYXJ5KGdncGxvdDIpCgojIEVuc3VyZSAnRGF0ZScgaW4gQ1JEX2FpcnBvcnQgaXMgaW4gRGF0ZSBmb3JtYXQKQ1JEX2FpcnBvcnQkRGF0ZSA8LSBhcy5EYXRlKENSRF9haXJwb3J0JERhdGUpCgojIFBsb3QgT2JzZXJ2ZWQgdnMgVW5jb3JyZWN0ZWQgUHJlZGljdGVkIFRlbXBlcmF0dXJlcwpQbG90IDwtIGdncGxvdCgpICsKICBnZW9tX2xpbmUoZGF0YSA9IENSXzQ1X3RyaW1tZWQsIGFlcyh4ID0gZGF0ZSwgeSA9IGF2Z190ZW1wZXJhdHVyZSwgY29sb3IgPSAiUHJlZGljdGVkIChVbmNvcnJlY3RlZCkiKSwgc2l6ZSA9IDEuMikgKwogIGdlb21fbGluZShkYXRhID0gQ1JEX2FpcnBvcnQsIGFlcyh4ID0gRGF0ZSwgeSA9IEFpcl9Nb250aEF2ZywgY29sb3IgPSAiT2JzZXJ2ZWQiKSwgc2l6ZSA9IDEuMikgKwogIGxhYnMoCiAgICB0aXRsZSA9ICJPYnNlcnZlZCB2cyBVbmNvcnJlY3RlZCBQcmVkaWN0ZWQgVGVtcGVyYXR1cmVzIC0gQ1IgNC41IiwKICAgIHggPSAiRGF0ZSIsCiAgICB5ID0gIlRlbXBlcmF0dXJlICjCsEMpIiwKICAgIGNvbG9yID0gIlRlbXBlcmF0dXJlIFR5cGUiCiAgKSArCiAgc2NhbGVfeF9kYXRlKAogICAgZGF0ZV9sYWJlbHMgPSAiJWIgJVkiLAogICAgZGF0ZV9icmVha3MgPSAiMSBtb250aCIsCiAgICBleHBhbmQgPSBjKDAsIDApCiAgKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoIlByZWRpY3RlZCAoVW5jb3JyZWN0ZWQpIiA9ICJyZWQiLCAiT2JzZXJ2ZWQiID0gImJsYWNrIikpICsKICB0aGVtZV9taW5pbWFsKCkgKwogIHRoZW1lKAogICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSwKICAgIGF4aXMudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyKSwKICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApLAogICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQsIGZhY2UgPSAiYm9sZCIpLAogICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiksCiAgICBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApCiAgKQpQbG90CgpnZ3NhdmUoIkJpYXNDb3JyZWN0aW9uL0dlb19CaWFzQ29ycmVjdGlvbi9QbG90cy9QcmUtQ29ycmVjdGlvbkNvbXBhcmlzb25fQ1I0NS5qcGVnIiwgcGxvdCA9IFBsb3QsIHdpZHRoID0gOCwgaGVpZ2h0ID0gNikKCmBgYAoKNS4gTW9udGhseSB6LXNjb3JlIGJpYXMgY29ycmVjdGlvbgoKYGBge3J9CiMgQWRkICJtb250aCIgY29sdW1uIGZvciBncm91cGluZwpDUl80NV90cmltbWVkJG1vbnRoIDwtIGZvcm1hdChDUl80NV90cmltbWVkJGRhdGUsICIlbSIpCkNSRF9haXJwb3J0JG1vbnRoIDwtIGZvcm1hdChDUkRfYWlycG9ydCREYXRlLCAiJW0iKQoKIyBDYWxjdWxhdGUgbW9udGhseSBtZWFucyBhbmQgc3RhbmRhcmQgZGV2aWF0aW9ucyBmb3Igb2JzZXJ2ZWQgYW5kIHByZWRpY3RlZCB0ZW1wZXJhdHVyZXMKb2JzX21vbnRobHlfc3RhdHMgPC0gQ1JEX2FpcnBvcnQgJT4lCiAgZ3JvdXBfYnkobW9udGgpICU+JQogIHN1bW1hcmlzZSgKICAgIG11X29icyA9IG1lYW4oQWlyX01vbnRoQXZnLCBuYS5ybSA9IFRSVUUpLAogICAgc2lnbWFfb2JzID0gc2QoQWlyX01vbnRoQXZnLCBuYS5ybSA9IFRSVUUpCiAgKQoKcHJlZF9tb250aGx5X3N0YXRzIDwtIENSXzQ1X3RyaW1tZWQgJT4lCiAgZ3JvdXBfYnkobW9udGgpICU+JQogIHN1bW1hcmlzZSgKICAgIG11X3ByZWQgPSBtZWFuKGF2Z190ZW1wZXJhdHVyZSwgbmEucm0gPSBUUlVFKSwKICAgIHNpZ21hX3ByZWQgPSBzZChhdmdfdGVtcGVyYXR1cmUsIG5hLnJtID0gVFJVRSkKICApCgojIE1lcmdlIHN0YXRpc3RpY3MgYmFjayBpbnRvIHRoZSBkYXRhc2V0CkNSXzQ1X3RyaW1tZWQgPC0gQ1JfNDVfdHJpbW1lZCAlPiUKICBsZWZ0X2pvaW4ob2JzX21vbnRobHlfc3RhdHMsIGJ5ID0gIm1vbnRoIikgJT4lCiAgbGVmdF9qb2luKHByZWRfbW9udGhseV9zdGF0cywgYnkgPSAibW9udGgiKQoKIyBBcHBseSBiaWFzIGNvcnJlY3Rpb24KQ1JfNDVfdHJpbW1lZCA8LSBDUl80NV90cmltbWVkICU+JQogIG11dGF0ZSgKICAgIGNvcnJlY3RlZF90ZW1wID0gKGF2Z190ZW1wZXJhdHVyZSAtIG11X3ByZWQpIC8gc2lnbWFfcHJlZCAqIHNpZ21hX29icyArIG11X29icwogICkKCmBgYAoKNi4gUGxvdCBjb3JyZWN0ZWQgZGF0YQoKYGBge3J9CiMgUGxvdHRpbmcgT2JzZXJ2ZWQgdnMgQ29ycmVjdGVkIFByZWRpY3RlZCBUZW1wZXJhdHVyZXMKUGxvdCA8LSBnZ3Bsb3QoKSArCiAgZ2VvbV9saW5lKGRhdGEgPSBDUl80NV90cmltbWVkLCBhZXMoeCA9IGRhdGUsIHkgPSBjb3JyZWN0ZWRfdGVtcCwgY29sb3IgPSAiUHJlZGljdGVkIChDb3JyZWN0ZWQpIiksIHNpemUgPSAxLjIsIGxpbmV0eXBlID0gImRhc2hlZCIpICsKICBnZW9tX2xpbmUoZGF0YSA9IENSRF9haXJwb3J0LCBhZXMoeCA9IERhdGUsIHkgPSBBaXJfTW9udGhBdmcsIGNvbG9yID0gIk9ic2VydmVkIiksIHNpemUgPSAxLjIpICsKICBsYWJzKAogICAgdGl0bGUgPSAiT2JzZXJ2ZWQgdnMgQ29ycmVjdGVkIFByZWRpY3RlZCBUZW1wZXJhdHVyZXMgLSBDUiBSQ1AgNC41IiwKICAgIHggPSAiRGF0ZSIsCiAgICB5ID0gIlRlbXBlcmF0dXJlICjCsEMpIiwKICAgIGNvbG9yID0gIlRlbXBlcmF0dXJlIFR5cGUiCiAgKSArCiAgc2NhbGVfeF9kYXRlKAogICAgZGF0ZV9sYWJlbHMgPSAiJWIgJVkiLAogICAgZGF0ZV9icmVha3MgPSAiMSBtb250aCIsCiAgICBleHBhbmQgPSBjKDAsIDApCiAgKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoIlByZWRpY3RlZCAoQ29ycmVjdGVkKSIgPSAiYmx1ZSIsICJPYnNlcnZlZCIgPSAiYmxhY2siKSkgKwogIHRoZW1lX21pbmltYWwoKSArCiAgdGhlbWUoCiAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpLAogICAgYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIpLAogICAgYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCksCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCwgZmFjZSA9ICJib2xkIiksCiAgICBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiwgZmFjZSA9ICJpdGFsaWMiKSwKICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIpLAogICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKQogICkKUGxvdAoKZ2dzYXZlKCJCaWFzQ29ycmVjdGlvbi9HZW9fQmlhc0NvcnJlY3Rpb24vUGxvdHMvQ29ycmVjdGVkX0NSNDUuanBlZyIsIHBsb3QgPSBQbG90LCB3aWR0aCA9IDgsIGhlaWdodCA9IDYpCgpgYGAKCjcuIENvcnJlY3Rpb24gYXBwbGllZCB0byB0aGUgd2hvbGUgZGF0YXNldAoKYGBge3J9CiMgQWRkICJtb250aCIgY29sdW1uIHRvIHRoZSBmdWxsIGRhdGFzZXQKQ1JfNDUkbW9udGggPC0gZm9ybWF0KENSXzQ1JGRhdGUsICIlbSIpCgojIE1lcmdlIG1vbnRobHkgc3RhdGlzdGljcyBpbnRvIHRoZSBmdWxsIGRhdGFzZXQKQ1JfNDUgPC0gQ1JfNDUgJT4lCiAgbGVmdF9qb2luKG9ic19tb250aGx5X3N0YXRzLCBieSA9ICJtb250aCIpICU+JQogIGxlZnRfam9pbihwcmVkX21vbnRobHlfc3RhdHMsIGJ5ID0gIm1vbnRoIikKCiMgQXBwbHkgdGhlIHotc2NvcmUgYmlhcyBjb3JyZWN0aW9uCkNSXzQ1IDwtIENSXzQ1ICU+JQogIG11dGF0ZSgKICAgIGNvcnJlY3RlZF90ZW1wID0gKGF2Z190ZW1wZXJhdHVyZSAtIG11X3ByZWQpIC8gc2lnbWFfcHJlZCAqIHNpZ21hX29icyArIG11X29icwogICkKCmBgYAoKOC4gUGxvdCBjb3JyZWN0ZWQgYW5kIHVuY29ycmVjdGVkIHRlbXBlcmF0dXJlcyB0b2dldGhlcgoKYGBge3J9CiMgUGxvdCB0aGUgZnVsbCBkYXRhc2V0IHdpdGggYWRqdXN0ZWQgeC1heGlzIGxpbWl0cwpQbG90IDwtIGdncGxvdCgpICsKICBnZW9tX2xpbmUoZGF0YSA9IENSXzQ1LCBhZXMoeCA9IGRhdGUsIHkgPSBhdmdfdGVtcGVyYXR1cmUsIGNvbG9yID0gIlByZWRpY3RlZCAoVW5jb3JyZWN0ZWQpIiksIHNpemUgPSAxLjIpICsKICBnZW9tX2xpbmUoZGF0YSA9IENSXzQ1LCBhZXMoeCA9IGRhdGUsIHkgPSBjb3JyZWN0ZWRfdGVtcCwgY29sb3IgPSAiUHJlZGljdGVkIChDb3JyZWN0ZWQpIiksIHNpemUgPSAxLjIsIGxpbmV0eXBlID0gImRhc2hlZCIpICsKICBsYWJzKAogICAgdGl0bGUgPSAiT3JpZ2luYWwgdnMgQ29ycmVjdGVkIFByZWRpY3RlZCBUZW1wZXJhdHVyZXMgLSBDUiBSQ1AgNC41IiwKICAgIHggPSAiRGF0ZSIsCiAgICB5ID0gIlRlbXBlcmF0dXJlICjCsEMpIiwKICAgIGNvbG9yID0gIlRlbXBlcmF0dXJlIFR5cGUiCiAgKSArCiAgc2NhbGVfeF9kYXRlKAogICAgbGltaXRzID0gYXMuRGF0ZShjKCIyMDEyLTAxLTAxIiwgIjIwMjAtMTItMDEiKSksICMgU2V0IHgtYXhpcyBsaW1pdHMKICAgIGRhdGVfbGFiZWxzID0gIiViICVZIiwKICAgIGRhdGVfYnJlYWtzID0gIjEgbW9udGgiLAogICAgZXhwYW5kID0gYygwLCAwKQogICkgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCJQcmVkaWN0ZWQgKFVuY29ycmVjdGVkKSIgPSAicmVkIiwgIlByZWRpY3RlZCAoQ29ycmVjdGVkKSIgPSAiYmx1ZSIpKSArCiAgdGhlbWVfbWluaW1hbCgpICsKICB0aGVtZSgKICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSksCiAgICBheGlzLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiksCiAgICBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSwKICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0LCBmYWNlID0gImJvbGQiKSwKICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIpLAogICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKQogICkKUGxvdAoKZ2dzYXZlKCJCaWFzQ29ycmVjdGlvbi9HZW9fQmlhc0NvcnJlY3Rpb24vUGxvdHMvQ29ycmVjdGlvbkNvbXBhcmlzb25fQ1I0NS5qcGVnIiwgcGxvdCA9IFBsb3QsIHdpZHRoID0gOCwgaGVpZ2h0ID0gNikKYGBgCgo5LiBQbG90IG9yaWdpbmFsIHZlcnN1cyBjb3JyZWN0ZWQgdGVtcGVyYXR1cmVzCgpgYGB7cn0KIyBQbG90IHRoZSBmdWxsIGRhdGFzZXQKUGxvdCA8LSBnZ3Bsb3QoKSArCiAgZ2VvbV9saW5lKGRhdGEgPSBDUl80NSwgYWVzKHggPSBkYXRlLCB5ID0gYXZnX3RlbXBlcmF0dXJlLCBjb2xvciA9ICJQcmVkaWN0ZWQgKFVuY29ycmVjdGVkKSIpLCBzaXplID0gMS4yKSArCiAgZ2VvbV9saW5lKGRhdGEgPSBDUl80NSwgYWVzKHggPSBkYXRlLCB5ID0gY29ycmVjdGVkX3RlbXAsIGNvbG9yID0gIlByZWRpY3RlZCAoQ29ycmVjdGVkKSIpLCBzaXplID0gMS4yLCBsaW5ldHlwZSA9ICJkYXNoZWQiKSArCiAgZ2VvbV9saW5lKGRhdGEgPSBDUkRfYWlycG9ydCwgYWVzKHggPSBEYXRlLCB5ID0gQWlyX01vbnRoQXZnLCBjb2xvciA9ICJPYnNlcnZlZCIpLCBzaXplID0gMS4yKSArCiAgbGFicygKICAgIHRpdGxlID0gIk9yaWdpbmFsIHZzIENvcnJlY3RlZCBQcmVkaWN0ZWQgVGVtcGVyYXR1cmVzIC0gQ1IgUkNQIDQuNSIsCiAgICB4ID0gIkRhdGUiLAogICAgeSA9ICJUZW1wZXJhdHVyZSAowrBDKSIsCiAgICBjb2xvciA9ICJUZW1wZXJhdHVyZSBUeXBlIgogICkgKwogIHNjYWxlX3hfZGF0ZSgKICAgIGRhdGVfbGFiZWxzID0gIiViICVZIiwKICAgIGRhdGVfYnJlYWtzID0gIjEgbW9udGgiLAogICAgZXhwYW5kID0gYygwLCAwKQogICkgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCJQcmVkaWN0ZWQgKFVuY29ycmVjdGVkKSIgPSAicmVkIiwgIlByZWRpY3RlZCAoQ29ycmVjdGVkKSIgPSAiYmx1ZSIpKSArCiAgdGhlbWVfbWluaW1hbCgpICsKICB0aGVtZSgKICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSksCiAgICBheGlzLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiksCiAgICBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSwKICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0LCBmYWNlID0gImJvbGQiKSwKICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIpLAogICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKQogICkKUGxvdAoKZ2dzYXZlKCJCaWFzQ29ycmVjdGlvbi9HZW9fQmlhc0NvcnJlY3Rpb24vUGxvdHMvRnVsbENvcnJlY3Rpb25fQ1I0NS5qcGVnIiwgcGxvdCA9IFBsb3QsIHdpZHRoID0gOCwgaGVpZ2h0ID0gNikKCmBgYAoKMTAuIFNhdmUgdGhlIG5ldyBmaWxlCgpgYGB7cn0KIyBTYXZlIHRoZSBjb3JyZWN0ZWQgZGF0YXNldCB0byBhIENTViBmaWxlCndyaXRlLmNzdihDUl80NSwgIkJpYXNDb3JyZWN0aW9uL0dlb19CaWFzQ29ycmVjdGlvbi9EYXRhRmlsZXMvU05BUF9DUjQ1X2NvcnJlY3RlZF9tb250aGx5LmNzdiIsIHJvdy5uYW1lcyA9IEZBTFNFKQoKYGBgCgoKIyBDb3BwZXIgUml2ZXIgRGVsdGEgUkNQIDguNQoKMS4gUmVhZCBpbiB0aGUgZGF0YQpgYGB7cn0KIyBSZWFkIGRhdGEgZmlsZXMKQ1JfODUgPC0gcmVhZC5jc3YoZmlsZSA9ICJCaWFzQ29ycmVjdGlvbi9HZW9fQmlhc0NvcnJlY3Rpb24vRGF0YUZpbGVzL1NOQVBfQ1I4NS5jc3YiKSAKQ1JfODUkZGF0ZSA8LSBhcy5EYXRlKENSXzg1JGRhdGUsZm9ybWF0PSIlWS0lbS0lZCIpCkNSRF9haXJwb3J0IDwtIHJlYWQuY3N2KGZpbGUgPSAiQmlhc0NvcnJlY3Rpb24vQ1JfUG9uZEFpclRlbXBfbWVhbi5jc3YiKQpDUkRfYWlycG9ydCA8LSBDUkRfYWlycG9ydCAlPiUgc2VsZWN0KC1YKSAgIyBSZW1vdmUgdW5uZWNlc3NhcnkgY29sdW1uICdYJwoKYGBgCgoyLiBDaGVjayBkYXRlcwoKYGBge3J9CiMgRW5zdXJlIHRoYXQgdGhlcmUgYXJlIG5vIE5BcyBpbiB0aGUgJ2RhdGUnIGNvbHVtbiBhZnRlciBjb252ZXJzaW9uCnN1bShpcy5uYShDUl84NSRkYXRlKSkgICMgQ2hlY2sgaWYgdGhlcmUgYXJlIGFueSBtaXNzaW5nIHZhbHVlcyAoc2hvdWxkIGJlIDApCgpgYGAKCjMuIFRyaW0gZGF0ZXMKCmBgYHtyfQojIFRyaW0gQ1JfODUgdG8gdGhlIGRhdGUgcmFuZ2Ugb2YgQ1JEX2FpcnBvcnQKc3RhcnRfZGF0ZSA8LSBtaW4oQ1JEX2FpcnBvcnQkRGF0ZSkKZW5kX2RhdGUgPC0gbWF4KENSRF9haXJwb3J0JERhdGUpCgojIFN1YnNldCBDUl84NSB0byBtYXRjaCB0aGUgZGF0ZSByYW5nZSBvZiBDUkRfYWlycG9ydApDUl84NV90cmltbWVkIDwtIENSXzg1ICU+JQogIGZpbHRlcihkYXRlID49IHN0YXJ0X2RhdGUgJiBkYXRlIDw9IGVuZF9kYXRlKQoKYGBgCgo0LiBQbG90IHByZS1jb3JyZWN0aW9uIGRhdGEKCmBgYHtyfQpsaWJyYXJ5KGdncGxvdDIpCgojIEVuc3VyZSAnRGF0ZScgaW4gQ1JEX2FpcnBvcnQgaXMgaW4gRGF0ZSBmb3JtYXQKQ1JEX2FpcnBvcnQkRGF0ZSA8LSBhcy5EYXRlKENSRF9haXJwb3J0JERhdGUpCgojIFBsb3QgT2JzZXJ2ZWQgdnMgVW5jb3JyZWN0ZWQgUHJlZGljdGVkIFRlbXBlcmF0dXJlcwpQbG90IDwtIGdncGxvdCgpICsKICBnZW9tX2xpbmUoZGF0YSA9IENSXzg1X3RyaW1tZWQsIGFlcyh4ID0gZGF0ZSwgeSA9IGF2Z190ZW1wZXJhdHVyZSwgY29sb3IgPSAiUHJlZGljdGVkIChVbmNvcnJlY3RlZCkiKSwgc2l6ZSA9IDEuMikgKwogIGdlb21fbGluZShkYXRhID0gQ1JEX2FpcnBvcnQsIGFlcyh4ID0gRGF0ZSwgeSA9IEFpcl9Nb250aEF2ZywgY29sb3IgPSAiT2JzZXJ2ZWQiKSwgc2l6ZSA9IDEuMikgKwogIGxhYnMoCiAgICB0aXRsZSA9ICJPYnNlcnZlZCB2cyBVbmNvcnJlY3RlZCBQcmVkaWN0ZWQgVGVtcGVyYXR1cmVzIC0gQ1IgOC41IiwKICAgIHggPSAiRGF0ZSIsCiAgICB5ID0gIlRlbXBlcmF0dXJlICjCsEMpIiwKICAgIGNvbG9yID0gIlRlbXBlcmF0dXJlIFR5cGUiCiAgKSArCiAgc2NhbGVfeF9kYXRlKAogICAgZGF0ZV9sYWJlbHMgPSAiJWIgJVkiLAogICAgZGF0ZV9icmVha3MgPSAiMSBtb250aCIsCiAgICBleHBhbmQgPSBjKDAsIDApCiAgKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoIlByZWRpY3RlZCAoVW5jb3JyZWN0ZWQpIiA9ICJyZWQiLCAiT2JzZXJ2ZWQiID0gImJsYWNrIikpICsKICB0aGVtZV9taW5pbWFsKCkgKwogIHRoZW1lKAogICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA4NSwgaGp1c3QgPSAxKSwKICAgIGF4aXMudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyKSwKICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApLAogICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQsIGZhY2UgPSAiYm9sZCIpLAogICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiksCiAgICBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApCiAgKQpQbG90CgpnZ3NhdmUoIkJpYXNDb3JyZWN0aW9uL0dlb19CaWFzQ29ycmVjdGlvbi9QbG90cy9QcmUtQ29ycmVjdGlvbkNvbXBhcmlzb25fQ1I4NS5qcGVnIiwgcGxvdCA9IFBsb3QsIHdpZHRoID0gOCwgaGVpZ2h0ID0gNikKCmBgYAoKNS4gTW9udGhseSB6LXNjb3JlIGJpYXMgY29ycmVjdGlvbgoKYGBge3J9CiMgQWRkICJtb250aCIgY29sdW1uIGZvciBncm91cGluZwpDUl84NV90cmltbWVkJG1vbnRoIDwtIGZvcm1hdChDUl84NV90cmltbWVkJGRhdGUsICIlbSIpCkNSRF9haXJwb3J0JG1vbnRoIDwtIGZvcm1hdChDUkRfYWlycG9ydCREYXRlLCAiJW0iKQoKIyBDYWxjdWxhdGUgbW9udGhseSBtZWFucyBhbmQgc3RhbmRhcmQgZGV2aWF0aW9ucyBmb3Igb2JzZXJ2ZWQgYW5kIHByZWRpY3RlZCB0ZW1wZXJhdHVyZXMKb2JzX21vbnRobHlfc3RhdHMgPC0gQ1JEX2FpcnBvcnQgJT4lCiAgZ3JvdXBfYnkobW9udGgpICU+JQogIHN1bW1hcmlzZSgKICAgIG11X29icyA9IG1lYW4oQWlyX01vbnRoQXZnLCBuYS5ybSA9IFRSVUUpLAogICAgc2lnbWFfb2JzID0gc2QoQWlyX01vbnRoQXZnLCBuYS5ybSA9IFRSVUUpCiAgKQoKcHJlZF9tb250aGx5X3N0YXRzIDwtIENSXzg1X3RyaW1tZWQgJT4lCiAgZ3JvdXBfYnkobW9udGgpICU+JQogIHN1bW1hcmlzZSgKICAgIG11X3ByZWQgPSBtZWFuKGF2Z190ZW1wZXJhdHVyZSwgbmEucm0gPSBUUlVFKSwKICAgIHNpZ21hX3ByZWQgPSBzZChhdmdfdGVtcGVyYXR1cmUsIG5hLnJtID0gVFJVRSkKICApCgojIE1lcmdlIHN0YXRpc3RpY3MgYmFjayBpbnRvIHRoZSBkYXRhc2V0CkNSXzg1X3RyaW1tZWQgPC0gQ1JfODVfdHJpbW1lZCAlPiUKICBsZWZ0X2pvaW4ob2JzX21vbnRobHlfc3RhdHMsIGJ5ID0gIm1vbnRoIikgJT4lCiAgbGVmdF9qb2luKHByZWRfbW9udGhseV9zdGF0cywgYnkgPSAibW9udGgiKQoKIyBBcHBseSBiaWFzIGNvcnJlY3Rpb24KQ1JfODVfdHJpbW1lZCA8LSBDUl84NV90cmltbWVkICU+JQogIG11dGF0ZSgKICAgIGNvcnJlY3RlZF90ZW1wID0gKGF2Z190ZW1wZXJhdHVyZSAtIG11X3ByZWQpIC8gc2lnbWFfcHJlZCAqIHNpZ21hX29icyArIG11X29icwogICkKCmBgYAoKNi4gUGxvdCBjb3JyZWN0ZWQgZGF0YQoKYGBge3J9CiMgUGxvdHRpbmcgT2JzZXJ2ZWQgdnMgQ29ycmVjdGVkIFByZWRpY3RlZCBUZW1wZXJhdHVyZXMKUGxvdCA8LSBnZ3Bsb3QoKSArCiAgZ2VvbV9saW5lKGRhdGEgPSBDUl84NV90cmltbWVkLCBhZXMoeCA9IGRhdGUsIHkgPSBjb3JyZWN0ZWRfdGVtcCwgY29sb3IgPSAiUHJlZGljdGVkIChDb3JyZWN0ZWQpIiksIHNpemUgPSAxLjIsIGxpbmV0eXBlID0gImRhc2hlZCIpICsKICBnZW9tX2xpbmUoZGF0YSA9IENSRF9haXJwb3J0LCBhZXMoeCA9IERhdGUsIHkgPSBBaXJfTW9udGhBdmcsIGNvbG9yID0gIk9ic2VydmVkIiksIHNpemUgPSAxLjIpICsKICBsYWJzKAogICAgdGl0bGUgPSAiT2JzZXJ2ZWQgdnMgQ29ycmVjdGVkIFByZWRpY3RlZCBUZW1wZXJhdHVyZXMgLSBDUiBSQ1AgOC41IiwKICAgIHggPSAiRGF0ZSIsCiAgICB5ID0gIlRlbXBlcmF0dXJlICjCsEMpIiwKICAgIGNvbG9yID0gIlRlbXBlcmF0dXJlIFR5cGUiCiAgKSArCiAgc2NhbGVfeF9kYXRlKAogICAgZGF0ZV9sYWJlbHMgPSAiJWIgJVkiLAogICAgZGF0ZV9icmVha3MgPSAiMSBtb250aCIsCiAgICBleHBhbmQgPSBjKDAsIDApCiAgKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoIlByZWRpY3RlZCAoQ29ycmVjdGVkKSIgPSAiYmx1ZSIsICJPYnNlcnZlZCIgPSAiYmxhY2siKSkgKwogIHRoZW1lX21pbmltYWwoKSArCiAgdGhlbWUoCiAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDg1LCBoanVzdCA9IDEpLAogICAgYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIpLAogICAgYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCksCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCwgZmFjZSA9ICJib2xkIiksCiAgICBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiwgZmFjZSA9ICJpdGFsaWMiKSwKICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIpLAogICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKQogICkKUGxvdAoKZ2dzYXZlKCJCaWFzQ29ycmVjdGlvbi9HZW9fQmlhc0NvcnJlY3Rpb24vUGxvdHMvQ29ycmVjdGVkX0NSODUuanBlZyIsIHBsb3QgPSBQbG90LCB3aWR0aCA9IDgsIGhlaWdodCA9IDYpCgpgYGAKCjcuIENvcnJlY3Rpb24gYXBwbGllZCB0byB0aGUgd2hvbGUgZGF0YXNldAoKYGBge3J9CiMgQWRkICJtb250aCIgY29sdW1uIHRvIHRoZSBmdWxsIGRhdGFzZXQKQ1JfODUkbW9udGggPC0gZm9ybWF0KENSXzg1JGRhdGUsICIlbSIpCgojIE1lcmdlIG1vbnRobHkgc3RhdGlzdGljcyBpbnRvIHRoZSBmdWxsIGRhdGFzZXQKQ1JfODUgPC0gQ1JfODUgJT4lCiAgbGVmdF9qb2luKG9ic19tb250aGx5X3N0YXRzLCBieSA9ICJtb250aCIpICU+JQogIGxlZnRfam9pbihwcmVkX21vbnRobHlfc3RhdHMsIGJ5ID0gIm1vbnRoIikKCiMgQXBwbHkgdGhlIHotc2NvcmUgYmlhcyBjb3JyZWN0aW9uCkNSXzg1IDwtIENSXzg1ICU+JQogIG11dGF0ZSgKICAgIGNvcnJlY3RlZF90ZW1wID0gKGF2Z190ZW1wZXJhdHVyZSAtIG11X3ByZWQpIC8gc2lnbWFfcHJlZCAqIHNpZ21hX29icyArIG11X29icwogICkKCmBgYAoKOC4gUGxvdCBjb3JyZWN0ZWQgYW5kIHVuY29ycmVjdGVkIHRlbXBlcmF0dXJlcyB0b2dldGhlcgoKYGBge3J9CiMgUGxvdCB0aGUgZnVsbCBkYXRhc2V0IHdpdGggYWRqdXN0ZWQgeC1heGlzIGxpbWl0cwpQbG90IDwtIGdncGxvdCgpICsKICBnZW9tX2xpbmUoZGF0YSA9IENSXzg1LCBhZXMoeCA9IGRhdGUsIHkgPSBhdmdfdGVtcGVyYXR1cmUsIGNvbG9yID0gIlByZWRpY3RlZCAoVW5jb3JyZWN0ZWQpIiksIHNpemUgPSAxLjIpICsKICBnZW9tX2xpbmUoZGF0YSA9IENSXzg1LCBhZXMoeCA9IGRhdGUsIHkgPSBjb3JyZWN0ZWRfdGVtcCwgY29sb3IgPSAiUHJlZGljdGVkIChDb3JyZWN0ZWQpIiksIHNpemUgPSAxLjIsIGxpbmV0eXBlID0gImRhc2hlZCIpICsKICBsYWJzKAogICAgdGl0bGUgPSAiT3JpZ2luYWwgdnMgQ29ycmVjdGVkIFByZWRpY3RlZCBUZW1wZXJhdHVyZXMgLSBDUiBSQ1AgOC41IiwKICAgIHggPSAiRGF0ZSIsCiAgICB5ID0gIlRlbXBlcmF0dXJlICjCsEMpIiwKICAgIGNvbG9yID0gIlRlbXBlcmF0dXJlIFR5cGUiCiAgKSArCiAgc2NhbGVfeF9kYXRlKAogICAgbGltaXRzID0gYXMuRGF0ZShjKCIyMDEyLTAxLTAxIiwgIjIwMjAtMTItMDEiKSksICMgU2V0IHgtYXhpcyBsaW1pdHMKICAgIGRhdGVfbGFiZWxzID0gIiViICVZIiwKICAgIGRhdGVfYnJlYWtzID0gIjEgbW9udGgiLAogICAgZXhwYW5kID0gYygwLCAwKQogICkgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCJQcmVkaWN0ZWQgKFVuY29ycmVjdGVkKSIgPSAicmVkIiwgIlByZWRpY3RlZCAoQ29ycmVjdGVkKSIgPSAiYmx1ZSIpKSArCiAgdGhlbWVfbWluaW1hbCgpICsKICB0aGVtZSgKICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSksCiAgICBheGlzLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiksCiAgICBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSwKICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0LCBmYWNlID0gImJvbGQiKSwKICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIpLAogICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKQogICkKUGxvdAoKZ2dzYXZlKCJCaWFzQ29ycmVjdGlvbi9HZW9fQmlhc0NvcnJlY3Rpb24vUGxvdHMvQ29ycmVjdGlvbkNvbXBhcmlzb25fQ1I4NS5qcGVnIiwgcGxvdCA9IFBsb3QsIHdpZHRoID0gOCwgaGVpZ2h0ID0gNikKYGBgCgo5LiBQbG90IG9yaWdpbmFsIHZlcnN1cyBjb3JyZWN0ZWQgdGVtcGVyYXR1cmVzCgpgYGB7cn0KIyBQbG90IHRoZSBmdWxsIGRhdGFzZXQKUGxvdCA8LSBnZ3Bsb3QoKSArCiAgZ2VvbV9saW5lKGRhdGEgPSBDUl84NSwgYWVzKHggPSBkYXRlLCB5ID0gYXZnX3RlbXBlcmF0dXJlLCBjb2xvciA9ICJQcmVkaWN0ZWQgKFVuY29ycmVjdGVkKSIpLCBzaXplID0gMS4yKSArCiAgZ2VvbV9saW5lKGRhdGEgPSBDUl84NSwgYWVzKHggPSBkYXRlLCB5ID0gY29ycmVjdGVkX3RlbXAsIGNvbG9yID0gIlByZWRpY3RlZCAoQ29ycmVjdGVkKSIpLCBzaXplID0gMS4yLCBsaW5ldHlwZSA9ICJkYXNoZWQiKSArCiAgZ2VvbV9saW5lKGRhdGEgPSBDUkRfYWlycG9ydCwgYWVzKHggPSBEYXRlLCB5ID0gQWlyX01vbnRoQXZnLCBjb2xvciA9ICJPYnNlcnZlZCIpLCBzaXplID0gMS4yKSArCiAgbGFicygKICAgIHRpdGxlID0gIk9yaWdpbmFsIHZzIENvcnJlY3RlZCBQcmVkaWN0ZWQgVGVtcGVyYXR1cmVzIC0gQ1IgUkNQIDguNSIsCiAgICB4ID0gIkRhdGUiLAogICAgeSA9ICJUZW1wZXJhdHVyZSAowrBDKSIsCiAgICBjb2xvciA9ICJUZW1wZXJhdHVyZSBUeXBlIgogICkgKwogIHNjYWxlX3hfZGF0ZSgKICAgIGRhdGVfbGFiZWxzID0gIiViICVZIiwKICAgIGRhdGVfYnJlYWtzID0gIjEgbW9udGgiLAogICAgZXhwYW5kID0gYygwLCAwKQogICkgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCJQcmVkaWN0ZWQgKFVuY29ycmVjdGVkKSIgPSAicmVkIiwgIlByZWRpY3RlZCAoQ29ycmVjdGVkKSIgPSAiYmx1ZSIpKSArCiAgdGhlbWVfbWluaW1hbCgpICsKICB0aGVtZSgKICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSksCiAgICBheGlzLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiksCiAgICBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSwKICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0LCBmYWNlID0gImJvbGQiKSwKICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIpLAogICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKQogICkKUGxvdAoKZ2dzYXZlKCJCaWFzQ29ycmVjdGlvbi9HZW9fQmlhc0NvcnJlY3Rpb24vUGxvdHMvRnVsbENvcnJlY3Rpb25fQ1I4NS5qcGVnIiwgcGxvdCA9IFBsb3QsIHdpZHRoID0gOCwgaGVpZ2h0ID0gNikKCmBgYAoKMTAuIFNhdmUgdGhlIG5ldyBmaWxlCgpgYGB7cn0KIyBTYXZlIHRoZSBjb3JyZWN0ZWQgZGF0YXNldCB0byBhIENTViBmaWxlCndyaXRlLmNzdihDUl84NSwgIkJpYXNDb3JyZWN0aW9uL0dlb19CaWFzQ29ycmVjdGlvbi9EYXRhRmlsZXMvU05BUF9DUjg1X2NvcnJlY3RlZF9tb250aGx5LmNzdiIsIHJvdy5uYW1lcyA9IEZBTFNFKQoKYGBgCgojIFlha3V0YXQgRm9yZWxhbmQgUkNQIDQuNQoKMS4gUmVhZCBpbiB0aGUgZGF0YQpgYGB7cn0KIyBSZWFkIGRhdGEgZmlsZXMKWUZfNDUgPC0gcmVhZC5jc3YoZmlsZSA9ICJCaWFzQ29ycmVjdGlvbi9HZW9fQmlhc0NvcnJlY3Rpb24vRGF0YUZpbGVzL1NOQVBfWUY0NS5jc3YiKSAKWUZfNDUkZGF0ZSA8LSBhcy5EYXRlKFlGXzQ1JGRhdGUsZm9ybWF0PSIlWS0lbS0lZCIpCllGX2FpcnBvcnQgPC0gcmVhZC5jc3YoZmlsZSA9ICJCaWFzQ29ycmVjdGlvbi9ZRl9Qb25kQWlyVGVtcF9tZWFuLmNzdiIpCllGX2FpcnBvcnQgPC0gWUZfYWlycG9ydCAlPiUgc2VsZWN0KC1YKSAgIyBSZW1vdmUgdW5uZWNlc3NhcnkgY29sdW1uICdYJwoKYGBgCgoyLiBDaGVjayBkYXRlcwoKYGBge3J9CiMgRW5zdXJlIHRoYXQgdGhlcmUgYXJlIG5vIE5BcyBpbiB0aGUgJ2RhdGUnIGNvbHVtbiBhZnRlciBjb252ZXJzaW9uCnN1bShpcy5uYShZRl80NSRkYXRlKSkgICMgQ2hlY2sgaWYgdGhlcmUgYXJlIGFueSBtaXNzaW5nIHZhbHVlcyAoc2hvdWxkIGJlIDApCgpgYGAKCjMuIFRyaW0gZGF0ZXMKCmBgYHtyfQojIFRyaW0gWUZfNDUgdG8gdGhlIGRhdGUgcmFuZ2Ugb2YgWUZfYWlycG9ydApzdGFydF9kYXRlIDwtIG1pbihZRl9haXJwb3J0JERhdGUpCmVuZF9kYXRlIDwtIG1heChZRl9haXJwb3J0JERhdGUpCgojIFN1YnNldCBZRl80NSB0byBtYXRjaCB0aGUgZGF0ZSByYW5nZSBvZiBZRl9haXJwb3J0CllGXzQ1X3RyaW1tZWQgPC0gWUZfNDUgJT4lCiAgZmlsdGVyKGRhdGUgPj0gc3RhcnRfZGF0ZSAmIGRhdGUgPD0gZW5kX2RhdGUpCgpgYGAKCjQuIFBsb3QgcHJlLWNvcnJlY3Rpb24gZGF0YQoKYGBge3J9CmxpYnJhcnkoZ2dwbG90MikKCiMgRW5zdXJlICdEYXRlJyBpbiBZRl9haXJwb3J0IGlzIGluIERhdGUgZm9ybWF0CllGX2FpcnBvcnQkRGF0ZSA8LSBhcy5EYXRlKFlGX2FpcnBvcnQkRGF0ZSkKCiMgUGxvdCBPYnNlcnZlZCB2cyBVbmNvcnJlY3RlZCBQcmVkaWN0ZWQgVGVtcGVyYXR1cmVzClBsb3QgPC0gZ2dwbG90KCkgKwogIGdlb21fbGluZShkYXRhID0gWUZfNDVfdHJpbW1lZCwgYWVzKHggPSBkYXRlLCB5ID0gYXZnX3RlbXBlcmF0dXJlLCBjb2xvciA9ICJQcmVkaWN0ZWQgKFVuY29ycmVjdGVkKSIpLCBzaXplID0gMS4yKSArCiAgZ2VvbV9saW5lKGRhdGEgPSBZRl9haXJwb3J0LCBhZXMoeCA9IERhdGUsIHkgPSBBaXJfTW9udGhBdmcsIGNvbG9yID0gIk9ic2VydmVkIiksIHNpemUgPSAxLjIpICsKICBnZW9tX2xpbmUoZGF0YSA9IFlGX2FpcnBvcnQsIGFlcyh4ID0gRGF0ZSwgeSA9IEFpcl9Nb250aEF2ZywgY29sb3IgPSAiT2JzZXJ2ZWQiKSwgc2l6ZSA9IDEuMikgKwogIGxhYnMoCiAgICB0aXRsZSA9ICJPYnNlcnZlZCB2cyBVbmNvcnJlY3RlZCBQcmVkaWN0ZWQgVGVtcGVyYXR1cmVzIC0gWUYgNC41IiwKICAgIHggPSAiRGF0ZSIsCiAgICB5ID0gIlRlbXBlcmF0dXJlICjCsEMpIiwKICAgIGNvbG9yID0gIlRlbXBlcmF0dXJlIFR5cGUiCiAgKSArCiAgc2NhbGVfeF9kYXRlKAogICAgZGF0ZV9sYWJlbHMgPSAiJWIgJVkiLAogICAgZGF0ZV9icmVha3MgPSAiMSBtb250aCIsCiAgICBleHBhbmQgPSBjKDAsIDApCiAgKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoIlByZWRpY3RlZCAoVW5jb3JyZWN0ZWQpIiA9ICJyZWQiLCAiT2JzZXJ2ZWQiID0gImJsYWNrIikpICsKICB0aGVtZV9taW5pbWFsKCkgKwogIHRoZW1lKAogICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSwKICAgIGF4aXMudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyKSwKICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApLAogICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQsIGZhY2UgPSAiYm9sZCIpLAogICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiksCiAgICBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApCiAgKQpQbG90CgpnZ3NhdmUoIkJpYXNDb3JyZWN0aW9uL0dlb19CaWFzQ29ycmVjdGlvbi9QbG90cy9QcmUtQ29ycmVjdGlvbkNvbXBhcmlzb25fWUY0NS5qcGVnIiwgcGxvdCA9IFBsb3QsIHdpZHRoID0gOCwgaGVpZ2h0ID0gNikKCmBgYAoKNS4gTW9udGhseSB6LXNjb3JlIGJpYXMgY29ycmVjdGlvbgoKYGBge3J9CiMgQWRkICJtb250aCIgY29sdW1uIGZvciBncm91cGluZwpZRl80NV90cmltbWVkJG1vbnRoIDwtIGZvcm1hdChZRl80NV90cmltbWVkJGRhdGUsICIlbSIpCllGX2FpcnBvcnQkbW9udGggPC0gZm9ybWF0KFlGX2FpcnBvcnQkRGF0ZSwgIiVtIikKCiMgQ2FsY3VsYXRlIG1vbnRobHkgbWVhbnMgYW5kIHN0YW5kYXJkIGRldmlhdGlvbnMgZm9yIG9ic2VydmVkIGFuZCBwcmVkaWN0ZWQgdGVtcGVyYXR1cmVzCm9ic19tb250aGx5X3N0YXRzIDwtIFlGX2FpcnBvcnQgJT4lCiAgZ3JvdXBfYnkobW9udGgpICU+JQogIHN1bW1hcmlzZSgKICAgIG11X29icyA9IG1lYW4oQWlyX01vbnRoQXZnLCBuYS5ybSA9IFRSVUUpLAogICAgc2lnbWFfb2JzID0gc2QoQWlyX01vbnRoQXZnLCBuYS5ybSA9IFRSVUUpCiAgKQoKcHJlZF9tb250aGx5X3N0YXRzIDwtIFlGXzQ1X3RyaW1tZWQgJT4lCiAgZ3JvdXBfYnkobW9udGgpICU+JQogIHN1bW1hcmlzZSgKICAgIG11X3ByZWQgPSBtZWFuKGF2Z190ZW1wZXJhdHVyZSwgbmEucm0gPSBUUlVFKSwKICAgIHNpZ21hX3ByZWQgPSBzZChhdmdfdGVtcGVyYXR1cmUsIG5hLnJtID0gVFJVRSkKICApCgojIE1lcmdlIHN0YXRpc3RpY3MgYmFjayBpbnRvIHRoZSBkYXRhc2V0CllGXzQ1X3RyaW1tZWQgPC0gWUZfNDVfdHJpbW1lZCAlPiUKICBsZWZ0X2pvaW4ob2JzX21vbnRobHlfc3RhdHMsIGJ5ID0gIm1vbnRoIikgJT4lCiAgbGVmdF9qb2luKHByZWRfbW9udGhseV9zdGF0cywgYnkgPSAibW9udGgiKQoKIyBBcHBseSBiaWFzIGNvcnJlY3Rpb24KWUZfNDVfdHJpbW1lZCA8LSBZRl80NV90cmltbWVkICU+JQogIG11dGF0ZSgKICAgIGNvcnJlY3RlZF90ZW1wID0gKGF2Z190ZW1wZXJhdHVyZSAtIG11X3ByZWQpIC8gc2lnbWFfcHJlZCAqIHNpZ21hX29icyArIG11X29icwogICkKCmBgYAoKNi4gUGxvdCBjb3JyZWN0ZWQgZGF0YQoKYGBge3J9CiMgUGxvdHRpbmcgT2JzZXJ2ZWQgdnMgQ29ycmVjdGVkIFByZWRpY3RlZCBUZW1wZXJhdHVyZXMKUGxvdCA8LSBnZ3Bsb3QoKSArCiAgZ2VvbV9saW5lKGRhdGEgPSBZRl80NV90cmltbWVkLCBhZXMoeCA9IGRhdGUsIHkgPSBjb3JyZWN0ZWRfdGVtcCwgY29sb3IgPSAiUHJlZGljdGVkIChDb3JyZWN0ZWQpIiksIHNpemUgPSAxLjIsIGxpbmV0eXBlID0gImRhc2hlZCIpICsKICBnZW9tX2xpbmUoZGF0YSA9IFlGX2FpcnBvcnQsIGFlcyh4ID0gRGF0ZSwgeSA9IEFpcl9Nb250aEF2ZywgY29sb3IgPSAiT2JzZXJ2ZWQiKSwgc2l6ZSA9IDEuMikgKwogIGxhYnMoCiAgICB0aXRsZSA9ICJPYnNlcnZlZCB2cyBDb3JyZWN0ZWQgUHJlZGljdGVkIFRlbXBlcmF0dXJlcyAtIFlGIFJDUCA0LjUiLAogICAgeCA9ICJEYXRlIiwKICAgIHkgPSAiVGVtcGVyYXR1cmUgKMKwQykiLAogICAgY29sb3IgPSAiVGVtcGVyYXR1cmUgVHlwZSIKICApICsKICBzY2FsZV94X2RhdGUoCiAgICBkYXRlX2xhYmVscyA9ICIlYiAlWSIsCiAgICBkYXRlX2JyZWFrcyA9ICIxIG1vbnRoIiwKICAgIGV4cGFuZCA9IGMoMCwgMCkKICApICsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygiUHJlZGljdGVkIChDb3JyZWN0ZWQpIiA9ICJibHVlIiwgIk9ic2VydmVkIiA9ICJibGFjayIpKSArCiAgdGhlbWVfbWluaW1hbCgpICsKICB0aGVtZSgKICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSksCiAgICBheGlzLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiksCiAgICBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSwKICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0LCBmYWNlID0gImJvbGQiKSwKICAgIHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyLCBmYWNlID0gIml0YWxpYyIpLAogICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiksCiAgICBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApCiAgKQpQbG90CgpnZ3NhdmUoIkJpYXNDb3JyZWN0aW9uL0dlb19CaWFzQ29ycmVjdGlvbi9QbG90cy9Db3JyZWN0ZWRfWUY0NS5qcGVnIiwgcGxvdCA9IFBsb3QsIHdpZHRoID0gOCwgaGVpZ2h0ID0gNikKCmBgYAoKNy4gQ29ycmVjdGlvbiBhcHBsaWVkIHRvIHRoZSB3aG9sZSBkYXRhc2V0CgpgYGB7cn0KIyBBZGQgIm1vbnRoIiBjb2x1bW4gdG8gdGhlIGZ1bGwgZGF0YXNldApZRl80NSRtb250aCA8LSBmb3JtYXQoWUZfNDUkZGF0ZSwgIiVtIikKCiMgTWVyZ2UgbW9udGhseSBzdGF0aXN0aWNzIGludG8gdGhlIGZ1bGwgZGF0YXNldApZRl80NSA8LSBZRl80NSAlPiUKICBsZWZ0X2pvaW4ob2JzX21vbnRobHlfc3RhdHMsIGJ5ID0gIm1vbnRoIikgJT4lCiAgbGVmdF9qb2luKHByZWRfbW9udGhseV9zdGF0cywgYnkgPSAibW9udGgiKQoKIyBBcHBseSB0aGUgei1zY29yZSBiaWFzIGNvcnJlY3Rpb24KWUZfNDUgPC0gWUZfNDUgJT4lCiAgbXV0YXRlKAogICAgY29ycmVjdGVkX3RlbXAgPSAoYXZnX3RlbXBlcmF0dXJlIC0gbXVfcHJlZCkgLyBzaWdtYV9wcmVkICogc2lnbWFfb2JzICsgbXVfb2JzCiAgKQoKYGBgCgo4LiBQbG90IGNvcnJlY3RlZCBhbmQgdW5jb3JyZWN0ZWQgdGVtcGVyYXR1cmVzIHRvZ2V0aGVyCgpgYGB7cn0KIyBQbG90IHRoZSBmdWxsIGRhdGFzZXQgd2l0aCBhZGp1c3RlZCB4LWF4aXMgbGltaXRzClBsb3QgPC0gZ2dwbG90KCkgKwogIGdlb21fbGluZShkYXRhID0gWUZfNDUsIGFlcyh4ID0gZGF0ZSwgeSA9IGF2Z190ZW1wZXJhdHVyZSwgY29sb3IgPSAiUHJlZGljdGVkIChVbmNvcnJlY3RlZCkiKSwgc2l6ZSA9IDEuMikgKwogIGdlb21fbGluZShkYXRhID0gWUZfNDUsIGFlcyh4ID0gZGF0ZSwgeSA9IGNvcnJlY3RlZF90ZW1wLCBjb2xvciA9ICJQcmVkaWN0ZWQgKENvcnJlY3RlZCkiKSwgc2l6ZSA9IDEuMiwgbGluZXR5cGUgPSAiZGFzaGVkIikgKwogIGxhYnMoCiAgICB0aXRsZSA9ICJPcmlnaW5hbCB2cyBDb3JyZWN0ZWQgUHJlZGljdGVkIFRlbXBlcmF0dXJlcyAtIFlGIFJDUCA0LjUiLAogICAgeCA9ICJEYXRlIiwKICAgIHkgPSAiVGVtcGVyYXR1cmUgKMKwQykiLAogICAgY29sb3IgPSAiVGVtcGVyYXR1cmUgVHlwZSIKICApICsKICBzY2FsZV94X2RhdGUoCiAgICBsaW1pdHMgPSBhcy5EYXRlKGMoIjIwMTItMDEtMDEiLCAiMjAyMC0xMi0wMSIpKSwgIyBTZXQgeC1heGlzIGxpbWl0cwogICAgZGF0ZV9sYWJlbHMgPSAiJWIgJVkiLAogICAgZGF0ZV9icmVha3MgPSAiMSBtb250aCIsCiAgICBleHBhbmQgPSBjKDAsIDApCiAgKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoIlByZWRpY3RlZCAoVW5jb3JyZWN0ZWQpIiA9ICJyZWQiLCAiUHJlZGljdGVkIChDb3JyZWN0ZWQpIiA9ICJibHVlIikpICsKICB0aGVtZV9taW5pbWFsKCkgKwogIHRoZW1lKAogICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSwKICAgIGF4aXMudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyKSwKICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApLAogICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQsIGZhY2UgPSAiYm9sZCIpLAogICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiksCiAgICBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApCiAgKQpQbG90CgpnZ3NhdmUoIkJpYXNDb3JyZWN0aW9uL0dlb19CaWFzQ29ycmVjdGlvbi9QbG90cy9Db3JyZWN0aW9uQ29tcGFyaXNvbl9ZRjQ1LmpwZWciLCBwbG90ID0gUGxvdCwgd2lkdGggPSA4LCBoZWlnaHQgPSA2KQpgYGAKCjkuIFBsb3Qgb3JpZ2luYWwgdmVyc3VzIGNvcnJlY3RlZCB0ZW1wZXJhdHVyZXMKCmBgYHtyfQojIFBsb3QgdGhlIGZ1bGwgZGF0YXNldApQbG90IDwtIGdncGxvdCgpICsKICBnZW9tX2xpbmUoZGF0YSA9IFlGXzQ1LCBhZXMoeCA9IGRhdGUsIHkgPSBhdmdfdGVtcGVyYXR1cmUsIGNvbG9yID0gIlByZWRpY3RlZCAoVW5jb3JyZWN0ZWQpIiksIHNpemUgPSAxLjIpICsKICBnZW9tX2xpbmUoZGF0YSA9IFlGXzQ1LCBhZXMoeCA9IGRhdGUsIHkgPSBjb3JyZWN0ZWRfdGVtcCwgY29sb3IgPSAiUHJlZGljdGVkIChDb3JyZWN0ZWQpIiksIHNpemUgPSAxLjIsIGxpbmV0eXBlID0gImRhc2hlZCIpICsKICBnZW9tX2xpbmUoZGF0YSA9IFlGX2FpcnBvcnQsIGFlcyh4ID0gRGF0ZSwgeSA9IEFpcl9Nb250aEF2ZywgY29sb3IgPSAiT2JzZXJ2ZWQiKSwgc2l6ZSA9IDEuMikgKwogIGxhYnMoCiAgICB0aXRsZSA9ICJPcmlnaW5hbCB2cyBDb3JyZWN0ZWQgUHJlZGljdGVkIFRlbXBlcmF0dXJlcyAtIFlGIFJDUCA0LjUiLAogICAgeCA9ICJEYXRlIiwKICAgIHkgPSAiVGVtcGVyYXR1cmUgKMKwQykiLAogICAgY29sb3IgPSAiVGVtcGVyYXR1cmUgVHlwZSIKICApICsKICBzY2FsZV94X2RhdGUoCiAgICBkYXRlX2xhYmVscyA9ICIlYiAlWSIsCiAgICBkYXRlX2JyZWFrcyA9ICIxIG1vbnRoIiwKICAgIGV4cGFuZCA9IGMoMCwgMCkKICApICsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygiUHJlZGljdGVkIChVbmNvcnJlY3RlZCkiID0gInJlZCIsICJQcmVkaWN0ZWQgKENvcnJlY3RlZCkiID0gImJsdWUiKSkgKwogIHRoZW1lX21pbmltYWwoKSArCiAgdGhlbWUoCiAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpLAogICAgYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIpLAogICAgYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCksCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCwgZmFjZSA9ICJib2xkIiksCiAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyKSwKICAgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCkKICApClBsb3QKCmdnc2F2ZSgiQmlhc0NvcnJlY3Rpb24vR2VvX0JpYXNDb3JyZWN0aW9uL1Bsb3RzL0Z1bGxDb3JyZWN0aW9uX1lGNDUuanBlZyIsIHBsb3QgPSBQbG90LCB3aWR0aCA9IDgsIGhlaWdodCA9IDYpCgpgYGAKCjEwLiBTYXZlIHRoZSBuZXcgZmlsZQoKYGBge3J9CiMgU2F2ZSB0aGUgY29ycmVjdGVkIGRhdGFzZXQgdG8gYSBDU1YgZmlsZQp3cml0ZS5jc3YoWUZfNDUsICJCaWFzQ29ycmVjdGlvbi9HZW9fQmlhc0NvcnJlY3Rpb24vRGF0YUZpbGVzL1NOQVBfWUY0NV9jb3JyZWN0ZWRfbW9udGhseS5jc3YiLCByb3cubmFtZXMgPSBGQUxTRSkKCmBgYAoKCiMgWWFrdXRhdCBGb3JlbGFuZCBSQ1AgOC41CgoxLiBSZWFkIGluIHRoZSBkYXRhCmBgYHtyfQojIFJlYWQgZGF0YSBmaWxlcwpZRl84NSA8LSByZWFkLmNzdihmaWxlID0gIkJpYXNDb3JyZWN0aW9uL0dlb19CaWFzQ29ycmVjdGlvbi9EYXRhRmlsZXMvU05BUF9ZRjg1LmNzdiIpIApZRl84NSRkYXRlIDwtIGFzLkRhdGUoWUZfODUkZGF0ZSxmb3JtYXQ9IiVZLSVtLSVkIikKWUZfYWlycG9ydCA8LSByZWFkLmNzdihmaWxlID0gIkJpYXNDb3JyZWN0aW9uL1lGX1BvbmRBaXJUZW1wX21lYW4uY3N2IikKWUZfYWlycG9ydCA8LSBZRl9haXJwb3J0ICU+JSBzZWxlY3QoLVgpICAjIFJlbW92ZSB1bm5lY2Vzc2FyeSBjb2x1bW4gJ1gnCgpgYGAKCjIuIENoZWNrIGRhdGVzCgpgYGB7cn0KIyBFbnN1cmUgdGhhdCB0aGVyZSBhcmUgbm8gTkFzIGluIHRoZSAnZGF0ZScgY29sdW1uIGFmdGVyIGNvbnZlcnNpb24Kc3VtKGlzLm5hKFlGXzg1JGRhdGUpKSAgIyBDaGVjayBpZiB0aGVyZSBhcmUgYW55IG1pc3NpbmcgdmFsdWVzIChzaG91bGQgYmUgMCkKCmBgYAoKMy4gVHJpbSBkYXRlcwoKYGBge3J9CiMgVHJpbSBZRl84NSB0byB0aGUgZGF0ZSByYW5nZSBvZiBZRl9haXJwb3J0CnN0YXJ0X2RhdGUgPC0gbWluKFlGX2FpcnBvcnQkRGF0ZSkKZW5kX2RhdGUgPC0gbWF4KFlGX2FpcnBvcnQkRGF0ZSkKCiMgU3Vic2V0IFlGXzg1IHRvIG1hdGNoIHRoZSBkYXRlIHJhbmdlIG9mIFlGX2FpcnBvcnQKWUZfODVfdHJpbW1lZCA8LSBZRl84NSAlPiUKICBmaWx0ZXIoZGF0ZSA+PSBzdGFydF9kYXRlICYgZGF0ZSA8PSBlbmRfZGF0ZSkKCmBgYAoKNC4gUGxvdCBwcmUtY29ycmVjdGlvbiBkYXRhCgpgYGB7cn0KbGlicmFyeShnZ3Bsb3QyKQoKIyBFbnN1cmUgJ0RhdGUnIGluIFlGX2FpcnBvcnQgaXMgaW4gRGF0ZSBmb3JtYXQKWUZfYWlycG9ydCREYXRlIDwtIGFzLkRhdGUoWUZfYWlycG9ydCREYXRlKQoKIyBQbG90IE9ic2VydmVkIHZzIFVuY29ycmVjdGVkIFByZWRpY3RlZCBUZW1wZXJhdHVyZXMKUGxvdCA8LSBnZ3Bsb3QoKSArCiAgZ2VvbV9saW5lKGRhdGEgPSBZRl84NV90cmltbWVkLCBhZXMoeCA9IGRhdGUsIHkgPSBhdmdfdGVtcGVyYXR1cmUsIGNvbG9yID0gIlByZWRpY3RlZCAoVW5jb3JyZWN0ZWQpIiksIHNpemUgPSAxLjIpICsKICBnZW9tX2xpbmUoZGF0YSA9IFlGX2FpcnBvcnQsIGFlcyh4ID0gRGF0ZSwgeSA9IEFpcl9Nb250aEF2ZywgY29sb3IgPSAiT2JzZXJ2ZWQiKSwgc2l6ZSA9IDEuMikgKwogIGxhYnMoCiAgICB0aXRsZSA9ICJPYnNlcnZlZCB2cyBVbmNvcnJlY3RlZCBQcmVkaWN0ZWQgVGVtcGVyYXR1cmVzIC0gWUYgOC41IiwKICAgIHggPSAiRGF0ZSIsCiAgICB5ID0gIlRlbXBlcmF0dXJlICjCsEMpIiwKICAgIGNvbG9yID0gIlRlbXBlcmF0dXJlIFR5cGUiCiAgKSArCiAgc2NhbGVfeF9kYXRlKAogICAgZGF0ZV9sYWJlbHMgPSAiJWIgJVkiLAogICAgZGF0ZV9icmVha3MgPSAiMSBtb250aCIsCiAgICBleHBhbmQgPSBjKDAsIDApCiAgKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoIlByZWRpY3RlZCAoVW5jb3JyZWN0ZWQpIiA9ICJyZWQiLCAiT2JzZXJ2ZWQiID0gImJsYWNrIikpICsKICB0aGVtZV9taW5pbWFsKCkgKwogIHRoZW1lKAogICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA4NSwgaGp1c3QgPSAxKSwKICAgIGF4aXMudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyKSwKICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApLAogICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQsIGZhY2UgPSAiYm9sZCIpLAogICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiksCiAgICBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApCiAgKQpQbG90CgpnZ3NhdmUoIkJpYXNDb3JyZWN0aW9uL0dlb19CaWFzQ29ycmVjdGlvbi9QbG90cy9QcmUtQ29ycmVjdGlvbkNvbXBhcmlzb25fWUY4NS5qcGVnIiwgcGxvdCA9IFBsb3QsIHdpZHRoID0gOCwgaGVpZ2h0ID0gNikKCmBgYAoKNS4gTW9udGhseSB6LXNjb3JlIGJpYXMgY29ycmVjdGlvbgoKYGBge3J9CiMgQWRkICJtb250aCIgY29sdW1uIGZvciBncm91cGluZwpZRl84NV90cmltbWVkJG1vbnRoIDwtIGZvcm1hdChZRl84NV90cmltbWVkJGRhdGUsICIlbSIpCllGX2FpcnBvcnQkbW9udGggPC0gZm9ybWF0KFlGX2FpcnBvcnQkRGF0ZSwgIiVtIikKCiMgQ2FsY3VsYXRlIG1vbnRobHkgbWVhbnMgYW5kIHN0YW5kYXJkIGRldmlhdGlvbnMgZm9yIG9ic2VydmVkIGFuZCBwcmVkaWN0ZWQgdGVtcGVyYXR1cmVzCm9ic19tb250aGx5X3N0YXRzIDwtIFlGX2FpcnBvcnQgJT4lCiAgZ3JvdXBfYnkobW9udGgpICU+JQogIHN1bW1hcmlzZSgKICAgIG11X29icyA9IG1lYW4oQWlyX01vbnRoQXZnLCBuYS5ybSA9IFRSVUUpLAogICAgc2lnbWFfb2JzID0gc2QoQWlyX01vbnRoQXZnLCBuYS5ybSA9IFRSVUUpCiAgKQoKcHJlZF9tb250aGx5X3N0YXRzIDwtIFlGXzg1X3RyaW1tZWQgJT4lCiAgZ3JvdXBfYnkobW9udGgpICU+JQogIHN1bW1hcmlzZSgKICAgIG11X3ByZWQgPSBtZWFuKGF2Z190ZW1wZXJhdHVyZSwgbmEucm0gPSBUUlVFKSwKICAgIHNpZ21hX3ByZWQgPSBzZChhdmdfdGVtcGVyYXR1cmUsIG5hLnJtID0gVFJVRSkKICApCgojIE1lcmdlIHN0YXRpc3RpY3MgYmFjayBpbnRvIHRoZSBkYXRhc2V0CllGXzg1X3RyaW1tZWQgPC0gWUZfODVfdHJpbW1lZCAlPiUKICBsZWZ0X2pvaW4ob2JzX21vbnRobHlfc3RhdHMsIGJ5ID0gIm1vbnRoIikgJT4lCiAgbGVmdF9qb2luKHByZWRfbW9udGhseV9zdGF0cywgYnkgPSAibW9udGgiKQoKIyBBcHBseSBiaWFzIGNvcnJlY3Rpb24KWUZfODVfdHJpbW1lZCA8LSBZRl84NV90cmltbWVkICU+JQogIG11dGF0ZSgKICAgIGNvcnJlY3RlZF90ZW1wID0gKGF2Z190ZW1wZXJhdHVyZSAtIG11X3ByZWQpIC8gc2lnbWFfcHJlZCAqIHNpZ21hX29icyArIG11X29icwogICkKCmBgYAoKNi4gUGxvdCBjb3JyZWN0ZWQgZGF0YQoKYGBge3J9CiMgUGxvdHRpbmcgT2JzZXJ2ZWQgdnMgQ29ycmVjdGVkIFByZWRpY3RlZCBUZW1wZXJhdHVyZXMKUGxvdCA8LSBnZ3Bsb3QoKSArCiAgZ2VvbV9saW5lKGRhdGEgPSBZRl84NV90cmltbWVkLCBhZXMoeCA9IGRhdGUsIHkgPSBjb3JyZWN0ZWRfdGVtcCwgY29sb3IgPSAiUHJlZGljdGVkIChDb3JyZWN0ZWQpIiksIHNpemUgPSAxLjIsIGxpbmV0eXBlID0gImRhc2hlZCIpICsKICBnZW9tX2xpbmUoZGF0YSA9IFlGX2FpcnBvcnQsIGFlcyh4ID0gRGF0ZSwgeSA9IEFpcl9Nb250aEF2ZywgY29sb3IgPSAiT2JzZXJ2ZWQiKSwgc2l6ZSA9IDEuMikgKwogIGxhYnMoCiAgICB0aXRsZSA9ICJPYnNlcnZlZCB2cyBDb3JyZWN0ZWQgUHJlZGljdGVkIFRlbXBlcmF0dXJlcyAtIFlGIFJDUCA4LjUiLAogICAgeCA9ICJEYXRlIiwKICAgIHkgPSAiVGVtcGVyYXR1cmUgKMKwQykiLAogICAgY29sb3IgPSAiVGVtcGVyYXR1cmUgVHlwZSIKICApICsKICBzY2FsZV94X2RhdGUoCiAgICBkYXRlX2xhYmVscyA9ICIlYiAlWSIsCiAgICBkYXRlX2JyZWFrcyA9ICIxIG1vbnRoIiwKICAgIGV4cGFuZCA9IGMoMCwgMCkKICApICsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygiUHJlZGljdGVkIChDb3JyZWN0ZWQpIiA9ICJibHVlIiwgIk9ic2VydmVkIiA9ICJibGFjayIpKSArCiAgdGhlbWVfbWluaW1hbCgpICsKICB0aGVtZSgKICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gODUsIGhqdXN0ID0gMSksCiAgICBheGlzLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiksCiAgICBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSwKICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0LCBmYWNlID0gImJvbGQiKSwKICAgIHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyLCBmYWNlID0gIml0YWxpYyIpLAogICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiksCiAgICBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApCiAgKQpQbG90CgpnZ3NhdmUoIkJpYXNDb3JyZWN0aW9uL0dlb19CaWFzQ29ycmVjdGlvbi9QbG90cy9Db3JyZWN0ZWRfWUY4NS5qcGVnIiwgcGxvdCA9IFBsb3QsIHdpZHRoID0gOCwgaGVpZ2h0ID0gNikKCmBgYAoKNy4gQ29ycmVjdGlvbiBhcHBsaWVkIHRvIHRoZSB3aG9sZSBkYXRhc2V0CgpgYGB7cn0KIyBBZGQgIm1vbnRoIiBjb2x1bW4gdG8gdGhlIGZ1bGwgZGF0YXNldApZRl84NSRtb250aCA8LSBmb3JtYXQoWUZfODUkZGF0ZSwgIiVtIikKCiMgTWVyZ2UgbW9udGhseSBzdGF0aXN0aWNzIGludG8gdGhlIGZ1bGwgZGF0YXNldApZRl84NSA8LSBZRl84NSAlPiUKICBsZWZ0X2pvaW4ob2JzX21vbnRobHlfc3RhdHMsIGJ5ID0gIm1vbnRoIikgJT4lCiAgbGVmdF9qb2luKHByZWRfbW9udGhseV9zdGF0cywgYnkgPSAibW9udGgiKQoKIyBBcHBseSB0aGUgei1zY29yZSBiaWFzIGNvcnJlY3Rpb24KWUZfODUgPC0gWUZfODUgJT4lCiAgbXV0YXRlKAogICAgY29ycmVjdGVkX3RlbXAgPSAoYXZnX3RlbXBlcmF0dXJlIC0gbXVfcHJlZCkgLyBzaWdtYV9wcmVkICogc2lnbWFfb2JzICsgbXVfb2JzCiAgKQoKYGBgCgo4LiBQbG90IGNvcnJlY3RlZCBhbmQgdW5jb3JyZWN0ZWQgdGVtcGVyYXR1cmVzIHRvZ2V0aGVyCgpgYGB7cn0KIyBQbG90IHRoZSBmdWxsIGRhdGFzZXQgd2l0aCBhZGp1c3RlZCB4LWF4aXMgbGltaXRzClBsb3QgPC0gZ2dwbG90KCkgKwogIGdlb21fbGluZShkYXRhID0gWUZfODUsIGFlcyh4ID0gZGF0ZSwgeSA9IGF2Z190ZW1wZXJhdHVyZSwgY29sb3IgPSAiUHJlZGljdGVkIChVbmNvcnJlY3RlZCkiKSwgc2l6ZSA9IDEuMikgKwogIGdlb21fbGluZShkYXRhID0gWUZfODUsIGFlcyh4ID0gZGF0ZSwgeSA9IGNvcnJlY3RlZF90ZW1wLCBjb2xvciA9ICJQcmVkaWN0ZWQgKENvcnJlY3RlZCkiKSwgc2l6ZSA9IDEuMiwgbGluZXR5cGUgPSAiZGFzaGVkIikgKwogIGxhYnMoCiAgICB0aXRsZSA9ICJPcmlnaW5hbCB2cyBDb3JyZWN0ZWQgUHJlZGljdGVkIFRlbXBlcmF0dXJlcyAtIFlGIFJDUCA4LjUiLAogICAgeCA9ICJEYXRlIiwKICAgIHkgPSAiVGVtcGVyYXR1cmUgKMKwQykiLAogICAgY29sb3IgPSAiVGVtcGVyYXR1cmUgVHlwZSIKICApICsKICBzY2FsZV94X2RhdGUoCiAgICBsaW1pdHMgPSBhcy5EYXRlKGMoIjIwMTItMDEtMDEiLCAiMjAyMC0xMi0wMSIpKSwgIyBTZXQgeC1heGlzIGxpbWl0cwogICAgZGF0ZV9sYWJlbHMgPSAiJWIgJVkiLAogICAgZGF0ZV9icmVha3MgPSAiMSBtb250aCIsCiAgICBleHBhbmQgPSBjKDAsIDApCiAgKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoIlByZWRpY3RlZCAoVW5jb3JyZWN0ZWQpIiA9ICJyZWQiLCAiUHJlZGljdGVkIChDb3JyZWN0ZWQpIiA9ICJibHVlIikpICsKICB0aGVtZV9taW5pbWFsKCkgKwogIHRoZW1lKAogICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSwKICAgIGF4aXMudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyKSwKICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApLAogICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQsIGZhY2UgPSAiYm9sZCIpLAogICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiksCiAgICBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApCiAgKQpQbG90CgpnZ3NhdmUoIkJpYXNDb3JyZWN0aW9uL0dlb19CaWFzQ29ycmVjdGlvbi9QbG90cy9Db3JyZWN0aW9uQ29tcGFyaXNvbl9ZRjg1LmpwZWciLCBwbG90ID0gUGxvdCwgd2lkdGggPSA4LCBoZWlnaHQgPSA2KQpgYGAKCjkuIFBsb3Qgb3JpZ2luYWwgdmVyc3VzIGNvcnJlY3RlZCB0ZW1wZXJhdHVyZXMKCmBgYHtyfQojIFBsb3QgdGhlIGZ1bGwgZGF0YXNldApQbG90IDwtIGdncGxvdCgpICsKICBnZW9tX2xpbmUoZGF0YSA9IFlGXzg1LCBhZXMoeCA9IGRhdGUsIHkgPSBhdmdfdGVtcGVyYXR1cmUsIGNvbG9yID0gIlByZWRpY3RlZCAoVW5jb3JyZWN0ZWQpIiksIHNpemUgPSAxLjIpICsKICBnZW9tX2xpbmUoZGF0YSA9IFlGXzg1LCBhZXMoeCA9IGRhdGUsIHkgPSBjb3JyZWN0ZWRfdGVtcCwgY29sb3IgPSAiUHJlZGljdGVkIChDb3JyZWN0ZWQpIiksIHNpemUgPSAxLjIsIGxpbmV0eXBlID0gImRhc2hlZCIpICsKICBnZW9tX2xpbmUoZGF0YSA9IFlGX2FpcnBvcnQsIGFlcyh4ID0gRGF0ZSwgeSA9IEFpcl9Nb250aEF2ZywgY29sb3IgPSAiT2JzZXJ2ZWQiKSwgc2l6ZSA9IDEuMikgKwogIGxhYnMoCiAgICB0aXRsZSA9ICJPcmlnaW5hbCB2cyBDb3JyZWN0ZWQgUHJlZGljdGVkIFRlbXBlcmF0dXJlcyAtIFlGIFJDUCA4LjUiLAogICAgeCA9ICJEYXRlIiwKICAgIHkgPSAiVGVtcGVyYXR1cmUgKMKwQykiLAogICAgY29sb3IgPSAiVGVtcGVyYXR1cmUgVHlwZSIKICApICsKICBzY2FsZV94X2RhdGUoCiAgICBkYXRlX2xhYmVscyA9ICIlYiAlWSIsCiAgICBkYXRlX2JyZWFrcyA9ICIxIG1vbnRoIiwKICAgIGV4cGFuZCA9IGMoMCwgMCkKICApICsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygiUHJlZGljdGVkIChVbmNvcnJlY3RlZCkiID0gInJlZCIsICJQcmVkaWN0ZWQgKENvcnJlY3RlZCkiID0gImJsdWUiKSkgKwogIHRoZW1lX21pbmltYWwoKSArCiAgdGhlbWUoCiAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpLAogICAgYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIpLAogICAgYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCksCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCwgZmFjZSA9ICJib2xkIiksCiAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyKSwKICAgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCkKICApClBsb3QKCmdnc2F2ZSgiQmlhc0NvcnJlY3Rpb24vR2VvX0JpYXNDb3JyZWN0aW9uL1Bsb3RzL0Z1bGxDb3JyZWN0aW9uX1lGODUuanBlZyIsIHBsb3QgPSBQbG90LCB3aWR0aCA9IDgsIGhlaWdodCA9IDYpCgpgYGAKCjEwLiBTYXZlIHRoZSBuZXcgZmlsZQoKYGBge3J9CiMgU2F2ZSB0aGUgY29ycmVjdGVkIGRhdGFzZXQgdG8gYSBDU1YgZmlsZQp3cml0ZS5jc3YoWUZfODUsICJCaWFzQ29ycmVjdGlvbi9HZW9fQmlhc0NvcnJlY3Rpb24vRGF0YUZpbGVzL1NOQVBfWUY4NV9jb3JyZWN0ZWRfbW9udGhseS5jc3YiLCByb3cubmFtZXMgPSBGQUxTRSkKCmBgYA==